home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianVisObjects.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  178KB  |  6,247 lines

  1. /*ScianVisObjects.c
  2.   May 28, 1991
  3.   Eric Pepke
  4.   Visualization objects in SciAn*/
  5.  
  6. #include "Scian.h"
  7. #include "ScianTypes.h"
  8. #include "ScianArrays.h"
  9. #include "ScianWindows.h"
  10. #include "ScianTextBoxes.h"
  11. #include "ScianButtons.h"
  12. #include "ScianTitleBoxes.h"
  13. #include "ScianObjWindows.h"
  14. #include "ScianIcons.h"
  15. #include "ScianColors.h"
  16. #include "ScianControls.h"
  17. #include "ScianLists.h"
  18. #include "ScianSpaces.h"
  19. #include "ScianLights.h"
  20. #include "ScianSliders.h"
  21. #include "ScianIDs.h"
  22. #include "ScianVisWindows.h"
  23. #include "ScianDatasets.h"
  24. #include "ScianPictures.h"
  25. #include "ScianDialogs.h"
  26. #include "ScianEvents.h"
  27. #include "ScianScripts.h"
  28. #include "ScianErrors.h"
  29. #include "ScianComplexControls.h"
  30. #include "ScianMethods.h"
  31. #include "ScianStyle.h"
  32. #include "ScianVisObjects.h"
  33. #include "ScianVisIso.h"
  34. #include "ScianVisContours.h"
  35. #include "ScianVisTraces.h"
  36. #include "ScianVisPoints.h"
  37. #include "ScianVisSticks.h"
  38. #include "ScianVisNumbers.h"
  39. #include "ScianFilters.h"
  40. #include "ScianDraw.h"
  41. #include "ScianObjFunctions.h"
  42. #include "ScianTemplates.h"
  43. #include "ScianTemplateHelper.h"
  44. #include "ScianSymbols.h"
  45. #include "ScianGeometry.h"
  46. #include "ScianScales.h"
  47. #include "ScianFontSystem.h"
  48.  
  49. #define AXISFACTOR    0.15        /*Factor of MAXSIZE to move axis name*/
  50. #define MAJORTICSIZE    0.05        /*Size of major tics*/
  51. #define LABELFACTOR    2.0        /*Offset of label*/
  52. #define MINORTICFACTOR    0.6        /*Size of minor tics*/
  53. #define BOUNDSEXPFACTOR    0.05        /*Factor to expand bounds for big bounds*/
  54.  
  55. ObjPtr visClass;            /*Class for all visualization objects*/
  56. ObjPtr visBounded;            /*Class for all bounded vis objects*/
  57. ObjPtr visAxes;                /*Class for all vis objects that can draw axes*/
  58. ObjPtr visWalls;            /*Class for all vis objects that have walls*/
  59. ObjPtr visSurface;            /*Class for all objects w/surface*/
  60. ObjPtr visDeformed;            /*Class for all objects w/deformed surface*/
  61. ObjPtr visColored;            /*Class for all objects colored*/
  62. ObjPtr visGeometryClass;        /*Class for all objects with geometry*/
  63. ObjPtr geoPictureClass;            /*Class for geometry picture*/
  64. ObjPtr visIcon;                /*Icon for vis object*/
  65. ObjPtr visLines;            /*Class for all objects w/lines*/
  66. ObjPtr visDots;                /*Class for all objects w/dots*/
  67. ObjPtr visSized;            /*Class for sizable object*/
  68.  
  69. Bool drawSolid = false;            /*True iff we want to draw solid*/
  70. real globalFactor, globalOffset, globalFixed;
  71. ObjPtr globalDeformObject;
  72. extern ObjPtr perspecControlClass;    /*Perspective control*/
  73. extern real spaceTime;
  74. ObjPtr allVisObjClasses;
  75.  
  76. /*Mapping from data to visualization techniques*/
  77. typedef struct
  78.     {
  79.     long dataInfo;            /*Info bits of the data*/
  80.     int topDim;            /*Topological dimension of the data iff HAS_FORM, -1 for don't care*/
  81.     int spatialDim;            /*Spacial dimension of the data iff HAS_FORM, -1 for don't care*/
  82.     int nComponents;        /*N components of the data, -1 for don't care.*/
  83.     ObjPtr visClass;
  84.     } VisMapping;
  85.  
  86. #define MAXNVISMAPPINGS    200        /*Maximum number of visualization maps*/
  87. int nVisMappings = 0;            /*Actual number of visualization maps*/
  88. VisMapping visMapping[MAXNVISMAPPINGS];
  89.  
  90. /*Serial number generator for visualization types*/
  91. typedef struct
  92.     {
  93.     char *name;
  94.     int regSerial;
  95.     int tempSerial;
  96.     } VisSerial;
  97. #define MAXNVISSERIALS    100
  98. int nVisSerials = 0;
  99. VisSerial visSerials[MAXNVISSERIALS];
  100.  
  101.  
  102. /*Internal prototypes*/
  103. #ifdef PROTO
  104. static Bool GetTicParams(ObjPtr object, real lowTic[3], int nTics[3], 
  105.     real ticSpace[3], int initMinor[3], int majorEvery[3]);
  106. #endif
  107.  
  108. float material[30];            /*Random material*/
  109.  
  110. void SetupDeformation(object)
  111. ObjPtr object;
  112. /*Sets up to do deformation based on object*/
  113. {
  114.     ObjPtr var;
  115.  
  116.     /*Get factor and offset*/
  117.     var = GetVar(object, DEFFACTOR);
  118.     if (var)
  119.     {
  120.     globalFactor = GetReal(var);
  121.     }
  122.     else
  123.     {
  124.     globalFactor = 1.0;
  125.     }
  126.     var = GetVar(object, DEFOFFSET);
  127.     if (var)
  128.     {
  129.     globalOffset = GetReal(var);
  130.     }
  131.     else
  132.     {
  133.     globalOffset = 0.0;
  134.     }
  135.  
  136.     globalDeformObject = GetVar(object, DEFORMOBJ);
  137.  
  138.     /*Make it deformed or not according to DEFORMSWITCH and DEFORMOBJ*/
  139.     if (!GetPredicate(object, DEFORMSWITCH))
  140.     {
  141.     globalDeformObject = NULLOBJ;
  142.     }
  143.  
  144.     if (globalDeformObject)
  145.     {
  146.     SetCurField(DEFORMFIELD, globalDeformObject);
  147.     SetCurForm(DEFORMFORM, globalDeformObject);
  148.     }
  149.  
  150.     var = GetVar(object, DEFCONSTANT);
  151.     if (var)
  152.     {
  153.     globalFixed = GetReal(var);
  154.     }
  155.     else
  156.     {
  157.     globalFixed = 0.0;
  158.     }
  159. }
  160.  
  161. int FindVisSerial(name)
  162. char *name;
  163. /*Finds a vis serial, returns it or -1*/
  164. {
  165.     int retVal;
  166.  
  167.     for (retVal = 0; retVal < nVisSerials; ++retVal)
  168.     {
  169.     char *s1, *s2;
  170.  
  171.     /*See if the name maps onto the first part of the object name*/
  172.     s1 = visSerials[retVal] . name;
  173.     s2 = name;
  174.     while (*s1)
  175.     {
  176.         if (toupper(*s1) != toupper(*s2)) break;
  177.         ++s1;
  178.         ++s2;
  179.     }
  180.     if (!(*s1))
  181.     {
  182.         return retVal;
  183.     }
  184.     }
  185.     return -1;
  186. }
  187.  
  188. void DefineVisMapping(dataInfo, topDim, spatialDim, nComponents, visClass)
  189. long dataInfo;
  190. int topDim, spatialDim, nComponents;
  191. ObjPtr visClass;
  192. /*Defines a mapping from a dataset class to a visualization class.
  193.   The first such mapping for a certain dataClass defines the preferred one.*/
  194. {
  195.     ObjPtr var;
  196.     visMapping[nVisMappings] . dataInfo = dataInfo;
  197.     visMapping[nVisMappings] . topDim = topDim;
  198.     visMapping[nVisMappings] . spatialDim = spatialDim;
  199.     visMapping[nVisMappings] . nComponents = nComponents;
  200.     visMapping[nVisMappings] . visClass = visClass;
  201.     ++nVisMappings;
  202.  
  203.     if (WhichListIndex(allVisObjClasses, visClass) < 0)
  204.     {
  205.     PostfixList(allVisObjClasses, visClass);
  206.     }
  207.  
  208.     /*See if it needs a new serial record*/
  209.     var = GetVar(visClass, NAME);
  210.  
  211.     if (var)
  212.     {
  213.     if (FindVisSerial(GetString(var)) < 0)
  214.     {
  215.         /*Need a new one*/
  216.         visSerials[nVisSerials] . name =
  217.         Alloc(strlen(GetString(var)) + 1);
  218.         strcpy(visSerials[nVisSerials] . name, GetString(var));
  219.         visSerials[nVisSerials] . regSerial = 0;
  220.         visSerials[nVisSerials] . tempSerial = 0;
  221.         ++nVisSerials;
  222.     }
  223.     }
  224. }
  225.  
  226. static ObjPtr MakeVisName(vis)
  227. ObjPtr vis;
  228. /*Makes the name of a visualization object*/
  229. {
  230.     Bool templatep;
  231.     int visSerial;
  232.     ObjPtr var;
  233.     char *name;
  234.  
  235.     templatep = GetPredicate(vis, TEMPLATEP);
  236.     var = GetVar(vis, NAME);
  237.     if (var)
  238.     {
  239.     name = GetString(var);
  240.     }
  241.     else
  242.     {
  243.     name = "Visualization";
  244.     }
  245.     visSerial = FindVisSerial(name);
  246.     if (visSerial >= 0)
  247.     {
  248.     if (templatep)
  249.     {
  250.         sprintf(tempStr, "%s Template %d",
  251.         visSerials[visSerial] . name, ++(visSerials[visSerial] . tempSerial));
  252.     }
  253.     else
  254.     {
  255.         sprintf(tempStr, "%s %d",
  256.         visSerials[visSerial] . name, ++(visSerials[visSerial] . regSerial));
  257.     }
  258.     SetVar(vis, NAME, NewString(tempStr));
  259.     }
  260.     return ObjTrue;
  261. }
  262.  
  263. #ifdef PROTO
  264. ObjPtr GetAllVis(ObjPtr dataset, Bool justOne, ObjPtr class)
  265. #else
  266. ObjPtr GetAllVis(dataset, justOne, class)
  267. ObjPtr dataset;
  268. Bool justOne;
  269. ObjPtr class;
  270. #endif
  271. /*Returns a list of all visualizations that can visualize dataset, or NULLOBJ
  272.   if justOne, returns the first it finds.  If class is not null, only 
  273.   returns visualizations belonging to that class*/
  274. {
  275.     int k;
  276.     long flags;
  277.     int topDim, spatialDim, nComponents;
  278.     ObjPtr var;
  279.     ObjPtr lastVis = 0;
  280.     ObjPtr list = NULLOBJ;
  281.     ObjPtr thisVis;
  282.  
  283.     /*Always apply some filters*/
  284.     dataset = MainFilters(dataset);
  285.  
  286.     flags = GetDatasetInfo(dataset);
  287.     flags &= ~DS_TIMEDEPENDENT;
  288.     spatialDim = GetSpatialDim(dataset);
  289.     topDim = GetTopDim(dataset);
  290.     if (flags & DS_VECTOR)
  291.     {
  292.     MakeVar(dataset, NCOMPONENTS);
  293.     var = GetIntVar("GetPrefVis", dataset, NCOMPONENTS);
  294.     if (!var)
  295.     {
  296.         return NULLOBJ;
  297.     }
  298.     nComponents = GetInt(var);
  299.     }
  300.  
  301.     /*Check all the possible visualization techniques on the raw dataset*/
  302.     for (k = 0; k < nVisMappings; ++k)
  303.     {
  304.     if ((visMapping[k] . dataInfo & ~DS_TIMEDEPENDENT) != flags)
  305.     {
  306.         continue;
  307.     }
  308.     if (visMapping[k] . topDim >= 0 && visMapping[k] . topDim != topDim)
  309.     {
  310.         continue;
  311.     }
  312.     if (flags & DS_HASFORM)
  313.     {
  314.         if (visMapping[k] . spatialDim >= 0 && visMapping[k] . spatialDim != spatialDim)
  315.         {
  316.         continue;
  317.         }
  318.     }
  319.     if (flags & DS_VECTOR)
  320.     {
  321.         if (visMapping[k] . nComponents >= 0 && visMapping[k] . nComponents != nComponents)
  322.         {
  323.         continue;
  324.         }
  325.     }
  326.     if (visMapping[k] . visClass == lastVis)
  327.     {
  328.         continue;
  329.     }
  330.     if (class && (visMapping[k] . visClass != class))
  331.     {
  332.         continue;
  333.     }
  334.     lastVis = visMapping[k] . visClass;
  335.     if (!list)
  336.     {
  337.         list = NewList();
  338.     }
  339.  
  340.     thisVis = NewVis(dataset, visMapping[k] . visClass);
  341.     if (thisVis)
  342.     {
  343.         PostfixList(list, thisVis);
  344.         if (justOne)
  345.         {
  346.         return list;
  347.         }
  348.     }
  349.     }
  350.  
  351.     lastVis = 0;
  352.     return list;
  353. }
  354.  
  355. ObjPtr GetPrefVis(dataSet)
  356. ObjPtr dataSet;
  357. /*Gets the preferred visualization for dataSet*/
  358. {
  359.     ObjPtr prefVis, list;
  360.  
  361.     if (prefVis = GetVar(dataSet, PREFVIS))
  362.     {
  363.     return NewVis(MainFilters(dataSet), prefVis);
  364.     }
  365.  
  366.     if (list = GetAllVis(dataSet, true, NULLOBJ))
  367.     {
  368.     ThingListPtr listOf;
  369.     listOf = LISTOF(list);
  370.     if (listOf)
  371.     {
  372.         return listOf -> thing;
  373.     }
  374.     }
  375.     return NULLOBJ;
  376. }
  377.  
  378. ObjPtr NewVis(dataset, visClass)
  379. ObjPtr dataset, visClass;
  380. /*Visializes dataset as a visualization object of class visClass.  If visClass
  381.   is NULLOBJ, picks the preferred visualization type.*/
  382. {
  383.     ObjPtr retVal;
  384.     FuncTyp method;
  385.  
  386.     if (!visClass)
  387.     {
  388.     visClass = GetPrefVis(dataset);
  389.     }
  390.  
  391.     retVal = NewObject(visClass, 0);
  392.     if (!retVal)
  393.     {
  394.     return NULLOBJ;
  395.     }
  396.  
  397.     method = GetMethod(retVal, SETMAINDATASET);
  398.     if (method)
  399.     {
  400.     (*method)(retVal, dataset);
  401.     }
  402.     else
  403.     {
  404.     /****UPDATE*** compatibility with obselete visualization objects*/
  405.     SetVar(retVal, REPOBJ, dataset);
  406.     SetVar(retVal, MAINDATASET, dataset);
  407.     }
  408.     SetVar(retVal, PARENTS, NewList());
  409.     method = GetMethod(retVal, INITIALIZE);
  410.     if (method)
  411.     {
  412.     ObjPtr result;
  413.     result = (*method)(retVal);
  414.     if (!IsTrue(result)) return NULLOBJ;
  415.     }
  416.  
  417.     return retVal;
  418. }
  419.  
  420. ObjPtr DropInMainDatasetCorral(corral, object, x, y)
  421. ObjPtr corral, object;
  422. int x, y;
  423. /*Drops an icon in a main dataset corral*/
  424. {
  425.     WarnUser(CW_CANNOTDROPINMAIN);
  426.     return ObjTrue;
  427. }
  428.  
  429. static ObjPtr DeleteVisObjectIcon(icon)
  430. ObjPtr icon;
  431. /*Deletes a visualization object associated with an icon*/
  432. {
  433.     ObjPtr space, contents, clock, parents, repObj;
  434.  
  435.     repObj = GetObjectVar("DeleteVisObjectIcon", icon, REPOBJ);
  436.     if (!repObj)
  437.     {
  438.     return ObjFalse;
  439.     }
  440.  
  441.     space = GetVar(icon, SPACE);
  442.     if (!space)
  443.     {
  444.     return ObjFalse;
  445.     }
  446.  
  447.     SetVar(repObj, SPACE, NULLOBJ);
  448.     contents = GetListVar("DeleteVisObjectIcon", space, CONTENTS);
  449.     if (!contents)
  450.     {
  451.     return ObjFalse;
  452.     }
  453.     DeleteFromList(contents, repObj);
  454.     parents = GetVar(repObj, PARENTS);
  455.     if (parents)
  456.     {
  457.     DeleteFromList(parents, space);
  458.     }
  459.     ImInvalid(space);
  460.  
  461.     /*Reinitialize the clock in the space*/
  462.     clock = GetVar(space, CLOCK);
  463.     if (clock)
  464.     {
  465.     ReinitController(clock);
  466.     }
  467.     return ObjTrue;
  468. }
  469.  
  470. ObjPtr NewVisIcon(visObject)
  471. ObjPtr visObject;
  472. /*Creates a new visualization icon for visObject*/
  473. {
  474.     ObjPtr name, defaultIcon, mainDataset;
  475.     ObjPtr retVal;
  476.  
  477.     MakeVar(visObject, DEFAULTICON);
  478.     defaultIcon = GetObjectVar("NewVisIcon", visObject, DEFAULTICON);
  479.     if (!defaultIcon)
  480.     {
  481.     return NULLOBJ;
  482.     }
  483.     retVal = NewObject(defaultIcon, 0);
  484.     if (!retVal)
  485.     {
  486.     return NULLOBJ;
  487.     }
  488.     SetMethod(retVal, DELETEICON, DeleteVisObjectIcon);
  489.  
  490.     SetVar(retVal, REPOBJ, visObject);
  491.  
  492.     MakeVar(visObject, NAME);
  493.     name = GetVar(visObject, NAME);
  494.     SetVar(retVal, NAME, name);
  495.  
  496.     mainDataset = GetObjectVar("NewVisIcon", visObject, MAINDATASET);
  497.     if (mainDataset)
  498.     {
  499.     name = GetLongName(mainDataset);
  500.     SetVar(retVal, FORMAT, name);
  501.     }
  502.     SetVar(retVal, ICONLOC, NULLOBJ);
  503.  
  504.     return retVal;
  505. }
  506.  
  507. static ObjPtr MakeFormBounds(object)
  508. ObjPtr object;
  509. /*Get bounds for an form-based object*/
  510. {
  511.     ObjPtr repObj, var;
  512.     real bounds[6];
  513.  
  514.     repObj = GetVar(object, MAINDATASET);
  515.     if (!repObj) repObj = GetObjectVar("FormBounds", object, REPOBJ);
  516.     if (repObj)
  517.     {
  518.     ObjPtr formObj;
  519.     MakeVar(repObj, DATAFORM);
  520.     formObj = GetVar(repObj, DATAFORM);
  521.     if (formObj)
  522.     {
  523.         long info;
  524.         info = GetDatasetInfo(repObj);
  525.         
  526.         {
  527.         ObjPtr curBoundsArray;
  528.  
  529.          curBoundsArray = GetArrayVar("FormBounds", formObj, BOUNDS);
  530.         if (!curBoundsArray)
  531.         {
  532.             return ObjFalse;
  533.         }
  534.         if (RANK(curBoundsArray) != 1)
  535.         {
  536.             ReportError("FormBounds", "Malformed BOUNDS\n");
  537.             return ObjFalse;
  538.         }
  539.         if (DIMS(curBoundsArray)[0] == 6)
  540.         {
  541.                 Array2CArray(bounds, curBoundsArray);
  542.         }
  543.         else if (DIMS(curBoundsArray)[0] == 4)
  544.         {
  545.                 Array2CArray(bounds, curBoundsArray);
  546.             bounds[4] = bounds[5] = 0.0;
  547.         }
  548.         else
  549.         {
  550.             return ObjFalse;
  551.         }
  552.         }
  553.     }
  554.     else
  555.     {
  556.         return ObjFalse;
  557.     }
  558.     var = NewRealArray(1, 6L);
  559.     CArray2Array(var, bounds);
  560.     SetVar(object, BOUNDS, var);
  561.     return ObjTrue;
  562.     }
  563.     else
  564.     {
  565.     return ObjFalse;
  566.     }
  567. }
  568.  
  569. static ObjPtr PrefixColoredDatasets(list, visObject)
  570. ObjPtr list, visObject;
  571. /*Prefixes the datasets in visObject to list*/
  572. {
  573.     ObjPtr colorObj; 
  574.     if (colorObj = GetVar(visObject, COLOROBJ))
  575.     {
  576.     PrefixList(list, colorObj);
  577.     }
  578. }
  579.  
  580. static ObjPtr MakeGeoPictureBounds(object)
  581. ObjPtr object;
  582. /*Makes bounds for a geopicture*/
  583. {
  584.     ObjPtr geometry, repObj, objBounds;
  585.     real *boundsPtr;
  586.     real bounds[6];
  587.     ObjPtr var;
  588.  
  589.     repObj = GetObjectVar("GeoPictureBounds", object, REPOBJ);
  590.     if (!repObj)
  591.     {
  592.     return ObjFalse;
  593.     }
  594.  
  595.     SetCurField(FIELD5, repObj);
  596.  
  597.     geometry = curFields[FIELD5] . objectInfo;
  598.     if (IsPicture(geometry))
  599.     {
  600.     GetPictureBounds(geometry, bounds);
  601.  
  602.     geometry = GetVar(repObj, ETERNALPART);
  603.     if (geometry)
  604.     {
  605.         real newBounds[6];
  606.         GetPictureBounds(geometry, newBounds);
  607.  
  608.         bounds[0] = MIN(bounds[0], newBounds[0]);
  609.         bounds[1] = MAX(bounds[1], newBounds[1]);
  610.         bounds[2] = MIN(bounds[2], newBounds[2]);
  611.         bounds[3] = MAX(bounds[3], newBounds[3]);
  612.         bounds[4] = MIN(bounds[4], newBounds[4]);
  613.         bounds[5] = MAX(bounds[5], newBounds[5]);
  614.     }
  615.  
  616.     objBounds = NewRealArray(1, (long) 6);
  617.     CArray2Array(objBounds, bounds);
  618.     SetVar(object, BOUNDS, objBounds);
  619.     }
  620.     else if (IsGeometry(geometry))
  621.     {
  622.     MakeFormBounds(object);
  623.     }
  624.     else if (geometry)
  625.     {
  626.     var = GetVar(geometry, CLASSID);
  627.     if (var && GetInt(var) == CLASS_TIMEDOBJ)
  628.     {
  629.         long k;
  630.         ObjPtr *elements;
  631.         real newBounds[6];
  632.  
  633.         var = GetVar(geometry, TIMEDATA);
  634.  
  635.         bounds[0] = bounds[2] = bounds[4] = plusInf;
  636.         bounds[1] = bounds[3] = bounds[5] = minusInf;
  637.  
  638.         if (var && IsObjArray(var))
  639.         {
  640.         elements = ELEMENTS(var);
  641.         for (k = 0; k < DIMS(var)[0]; ++k)
  642.         {
  643.             GetPictureBounds(elements[k], newBounds);
  644.  
  645.             bounds[0] = MIN(bounds[0], newBounds[0]);
  646.             bounds[1] = MAX(bounds[1], newBounds[1]);
  647.             bounds[2] = MIN(bounds[2], newBounds[2]);
  648.             bounds[3] = MAX(bounds[3], newBounds[3]);
  649.             bounds[4] = MIN(bounds[4], newBounds[4]);
  650.             bounds[5] = MAX(bounds[5], newBounds[5]);
  651.         }
  652.         }
  653.         else
  654.         {
  655.         ReportError("MakeGeoPictureBounds", "Time error");
  656.         }
  657.         geometry = GetVar(repObj, ETERNALPART);
  658.         if (geometry)
  659.         {
  660.         GetPictureBounds(geometry, newBounds);
  661.         bounds[0] = MIN(bounds[0], newBounds[0]);
  662.         bounds[1] = MAX(bounds[1], newBounds[1]);
  663.         bounds[2] = MIN(bounds[2], newBounds[2]);
  664.         bounds[3] = MAX(bounds[3], newBounds[3]);
  665.         bounds[4] = MIN(bounds[4], newBounds[4]);
  666.         bounds[5] = MAX(bounds[5], newBounds[5]);
  667.         }
  668.     }
  669.     objBounds = NewRealArray(1, (long) 6);
  670.     CArray2Array(objBounds, bounds);
  671.     SetVar(object, BOUNDS, objBounds);
  672.     }
  673.  
  674.     return ObjTrue;
  675. }
  676.  
  677. static ObjPtr ChangeReflection(object)
  678. ObjPtr object;
  679. /*Changed value for a reflection quality control*/
  680. {
  681.     real shininess, specularity;
  682.     ObjPtr val;
  683.     ObjPtr repObj;
  684.  
  685.     repObj = GetObjectVar("ChangeReflection", object, REPOBJ);
  686.     if (!repObj)
  687.     {
  688.     return ObjFalse;
  689.     }
  690.  
  691.     if (!GetXYControlValue(object, &shininess, &specularity))
  692.     {
  693.     return ObjFalse;
  694.     }
  695.  
  696.     SetVar(repObj, SHINVAL, NewReal(shininess));
  697.     SetVar(repObj, SPECVAL, NewReal(specularity));
  698.     ImInvalid(repObj);
  699.     SetVar(object, APPEARANCE, ObjTrue);
  700.     return ObjTrue;
  701. }
  702.  
  703. static ObjPtr MakeReflectionAppearance(object)
  704. ObjPtr object;
  705. /*Makes the appearance of a reflection quality control*/
  706. {
  707.     real shininess, specularity;
  708.     ObjPtr val;
  709.     ObjPtr repObj;
  710.     ObjPtr var;
  711.     real *elements;
  712.     FuncTyp method;
  713.  
  714.     repObj = GetObjectVar("MakeReflectionAppearance", object, REPOBJ);
  715.     if (!repObj)
  716.     {
  717.     return ObjFalse;
  718.     }
  719.  
  720.     var = GetRealVar("MakeReflectionAppearance", repObj, SHINVAL);
  721.     if (!var)
  722.     {
  723.     return ObjFalse;
  724.     }
  725.     shininess = GetReal(var);
  726.  
  727.     var = GetRealVar("MakeReflectionAppearance", repObj, SPECVAL);
  728.     if (!var)
  729.     {
  730.     return ObjFalse;
  731.     }
  732.     specularity = GetReal(var);
  733.  
  734.     val = NewRealArray(1, 2L);
  735.     elements = ELEMENTS(val);
  736.     elements[0] = shininess;
  737.     elements[1] = specularity;
  738.  
  739.     method = GetMethod(object, CHANGEDVALUE);
  740.     SetMethod(object, CHANGEDVALUE, (FuncTyp) 0);
  741.     SetValue(object, val);
  742.     SetMethod(object, CHANGEDVALUE, method);
  743.  
  744.     SetVar(object, APPEARANCE, ObjTrue);
  745.     return ObjTrue;
  746. }
  747.  
  748. static ObjPtr ShowVisControls(object, windowName)
  749. ObjPtr object;
  750. char *windowName;
  751. /*Makes a new control window to control visualization object*/
  752. {
  753.     WinInfoPtr controlWindow;
  754.     ObjPtr var;
  755.     ObjPtr panel;
  756.     ObjPtr controlField;
  757.     ObjPtr contents;
  758.     ObjPtr curObj;
  759.     ObjPtr firstButton = NULLOBJ;
  760.     int left, right, bottom, top, width;
  761.     WinInfoPtr dialogExists;
  762.     Bool abortp = false;
  763.  
  764.     dialogExists = DialogExists((WinInfoPtr) object, NewString("Controls"));
  765.     controlWindow = GetDialog((WinInfoPtr) object, NewString("Controls"), windowName, 
  766.     CWINWIDTH, CWINHEIGHT, CWINWIDTH, CWINHEIGHT, WINFIXEDSIZE + WINUI);
  767.     
  768.     if (!dialogExists)
  769.     {
  770.     SetVar((ObjPtr) controlWindow, REPOBJ, object);
  771.  
  772.     /*Add in help string*/
  773.     SetVar((ObjPtr) controlWindow, HELPSTRING,
  774.         NewString("This window shows controls for a visualization object.  \
  775. At the right is an icon corral showing a series of icons.  Each icon represents a \
  776. set of attributes of the visualization object.  On the left are the controls for \
  777. the selected set of attributes.  \
  778. Use Help In Context and click on the various controls to find out what they do.  \
  779. Click on a different icon to choose a different set of attributes."));
  780.  
  781.     /*Add in a panel*/
  782.     panel = NewPanel(greyPanelClass, 0, CWINWIDTH, 0, CWINHEIGHT);
  783.     if (!panel)
  784.     {
  785.         return ObjFalse;
  786.     }
  787.     contents = GetVar((ObjPtr) controlWindow, CONTENTS);
  788.     PrefixList(contents, panel);
  789.     SetVar(panel, PARENT, (ObjPtr) controlWindow);
  790.  
  791.     contents = GetVar(panel, CONTENTS);
  792.  
  793.     /*Add in a control field*/
  794.     controlField = NewControlField(CWINWIDTH - CORRALBORDER - CWINCORRALWIDTH,
  795.                    CWINWIDTH - CORRALBORDER,
  796.                    CORRALBORDER,
  797.                    CWINHEIGHT - CORRALBORDER,
  798.                 "Visualization Object Attributes", OBJECTSFROMTOP | BARRIGHT);
  799.     SetVar(controlField, HELPSTRING,
  800.        NewString("This icon button group shows sets of attributes of the visualization \
  801. object that can be modified.  The left side of the panel shows controls for the \
  802. attribute given by the selected icon button.  To show another set of \
  803. attributes, press another button."));
  804.     SetVar(controlField, PARENT, panel);
  805.     PrefixList(contents, controlField);
  806.  
  807.     contents = GetVar(controlField, CONTENTS);
  808.  
  809.     /*Fill the control field up with buttons*/
  810.     curObj = object;
  811.     top = -MAJORBORDER;
  812.     width = CWINCCWIDTH;
  813.     while (curObj)
  814.     {
  815.         ObjPtr icon;
  816.         icon = Get1Var(curObj, CONTROLICON);
  817.         if (icon)
  818.         {
  819.         ObjPtr button;
  820.         ObjPtr panelContents;
  821.         FuncTyp method;
  822.         int whichIcon;
  823.         char *name;
  824.  
  825.         if (firstButton && abortp) break;
  826.  
  827.         var = GetIntVar("ShowVisControls", icon, WHICHICON);
  828.         if (var)
  829.         {
  830.             whichIcon = GetInt(var);
  831.         }
  832.         else
  833.         {
  834.             whichIcon = ICONQUESTION;
  835.         }
  836.  
  837.         var = GetStringVar("ShowVisControls", icon, NAME);
  838.         if (var)
  839.         {
  840.             name = GetString(var);
  841.         }
  842.         else
  843.         {
  844.             name = "Unknown";
  845.         }
  846.  
  847.         button = NewIconLabeledButton(0, width, top - CWINICONBUTHEIGHT, top,
  848.             whichIcon, UIYELLOW, name, BS_PITTED);
  849.         SetMethod(button, ICONEXTRADRAW, GetMethod(icon, ICONEXTRADRAW));
  850.         SetVar(button, REPOBJ, object);
  851.         SetMethod(button, CHANGEDVALUE, ChangeControlPanelButton);
  852.  
  853.         SetVar(button, PANEL, panel);
  854.  
  855.         /*Make a new panel contents just for this button*/
  856.         panelContents = NewList();
  857.         PrefixList(panelContents, controlField);
  858.         SetVar(panelContents, PARENT, panel);
  859.         SetVar(button, PANELCONTENTS, panelContents);
  860.         SetVar(button, PARENT, panelContents);
  861.  
  862.         /*Give the button a chance to add controls*/
  863.         method = Get1Method(curObj, ADDCONTROLS);
  864.         if (method)
  865.         {
  866.             SetVar(button, CONTROLSADDED, ObjFalse);
  867.             SetMethod(button, ADDCONTROLS, method);
  868.         }
  869.         else
  870.         {
  871.             SetVar(button, CONTROLSADDED, ObjTrue);
  872.         }
  873.         PrefixList(contents, button);
  874.         SetVar(button, PARENT, controlField);
  875.         top -= CWINICONBUTHEIGHT + MINORBORDER;
  876.     
  877.         if (!firstButton)
  878.         {
  879.             ObjPtr mainDataset;
  880.     
  881.             firstButton = button;
  882.             /*Give the MAINDATASET a chance to set controls*/
  883.             mainDataset = GetVar(object, MAINDATASET);
  884.             while (mainDataset)
  885.             {
  886.             icon = GetVar(mainDataset, CONTROLICON);
  887.             if (icon)
  888.             {
  889.                 ObjPtr panelContents;
  890.                 FuncTyp method;
  891.     
  892.                 var = GetIntVar("ShowVisControls", icon, WHICHICON);
  893.                 if (var)
  894.                 {
  895.                 whichIcon = GetInt(var);
  896.                 }
  897.                 else
  898.                 {
  899.                 whichIcon = ICONQUESTION;
  900.                 }
  901.     
  902.                 var = GetStringVar("ShowVisControls", icon, NAME);
  903.                 if (var)
  904.                 {
  905.                 name = GetString(var);
  906.                 }
  907.                 else
  908.                 {
  909.                 name = "Unknown";
  910.                 }
  911.             
  912.                 button = NewIconLabeledButton(0, width, top - CWINICONBUTHEIGHT, top,
  913.                     whichIcon, UIYELLOW, name, BS_PITTED);
  914.                 SetMethod(button, ICONEXTRADRAW, GetMethod(icon, ICONEXTRADRAW));
  915.     
  916.                 SetMethod(button, CHANGEDVALUE, ChangeControlPanelButton);
  917.     
  918.                 SetVar(button, PANEL, panel);
  919.     
  920.                 /*Make a new panel contents just for this button*/
  921.                 panelContents = NewList();
  922.                 PrefixList(panelContents, controlField);
  923.                 SetVar(panelContents, PARENT, panel);
  924.                 SetVar(button, PANELCONTENTS, panelContents);
  925.                 SetVar(button, PARENT, panelContents);
  926.                 SetVar(button, REPOBJ, mainDataset);
  927.  
  928.                 /*Give the button a chance to add controls*/
  929.                 method = GetMethod(mainDataset, ADDCONTROLS);
  930.                 if (method)
  931.                 {
  932.                 SetVar(button, CONTROLSADDED, ObjFalse);
  933.                 SetMethod(button, ADDCONTROLS, method);
  934.                 }
  935.                 else
  936.                 {
  937.                 SetVar(button, CONTROLSADDED, ObjTrue);
  938.                 }
  939.                 PrefixList(contents, button);
  940.                 SetVar(button, PARENT, controlField);
  941.                 top -= CWINICONBUTHEIGHT + MINORBORDER;
  942.             }
  943.             mainDataset = GetVar(mainDataset, MAINDATASET);
  944.             }
  945.         }
  946.         }
  947.         if (GetPredicate(curObj, ABORTCONTROLS)) abortp = true;
  948.         curObj = ClassOf(curObj);
  949.     }
  950.  
  951.     /*Adjust the scroll bars*/
  952.     RecalcScroll(controlField);
  953.  
  954.     if (firstButton)
  955.     {
  956.         SetValue(firstButton, NewInt(1));
  957.         SetVar(controlField, BUTTON, firstButton);
  958.     }
  959.     }
  960.  
  961.     return (ObjPtr) controlWindow;
  962. }
  963.  
  964. static char *wallNames[6] =
  965.     {
  966.     "-X Wall",
  967.     "+X Wall",
  968.     "-Y Wall",
  969.     "+Y Wall",
  970.     "-Z Wall (Floor)",
  971.     "+Z Wall (Ceiling)"
  972.     };
  973.  
  974. #ifdef PROTO
  975. void AppendSpaces(char *s, int nSpaces)
  976. #else
  977. void AppendSpaces(s, nSpaces)
  978. char *s;
  979. int nSpaces;
  980. #endif
  981. /*Appends nSpaces spaces after s*/
  982. {
  983.     while (*s) ++s;
  984.  
  985.     while (nSpaces--)
  986.     {
  987.     *s++ = ' ';
  988.     }
  989.     *s = '\0';
  990. }
  991.  
  992. static ObjPtr AddAxesControls(object, panelContents)
  993. ObjPtr object, panelContents;
  994. /*Adds controls for a visualization object with axes*/
  995. {
  996.     ObjPtr titleBox, checkBox, textBox, var;
  997.     ObjPtr colorWheel, slider;
  998.     int curFlag;
  999.     int left, right, bottom, top, mid, width, i, j, whichWall, k, f, h;
  1000.     int l, r, b, t;
  1001.     int titleWidth, buttonWidth, axisGroupWidth, rightWidth;
  1002.     char buttonName[40];
  1003.  
  1004.     width = CWINWIDTH - CORRALBORDER - CWINCORRALWIDTH;
  1005.     top = CWINHEIGHT - MINORBORDER;
  1006.     rightWidth = (width - 2 * MINORBORDER - SBFUNCTIONNAMEWIDTH);
  1007.  
  1008.     /*Axis name edit boxes*/
  1009.     MakeVar(object, XNAME);
  1010.     MakeVar(object, YNAME);
  1011.     MakeVar(object, ZNAME);
  1012.  
  1013.     left = MINORBORDER;
  1014.     right = left + SBFUNCTIONNAMEWIDTH;
  1015.     bottom = top - EDITBOXHEIGHT;
  1016.     mid = (bottom + top) / 2;
  1017.     textBox = NewTextBox(left, right, 
  1018.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1019.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1020.             0, "Axis Name Text", "Axis Name:"); 
  1021.     PrefixList(panelContents, textBox);
  1022.     SetVar(textBox, PARENT, panelContents);
  1023.     left = right;
  1024.  
  1025.     for (k = 0; k < 3; ++k)
  1026.     {
  1027.     /*Make the axis edit box*/
  1028.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1029.     right = left + rightWidth / 3 - MINORBORDER;
  1030.  
  1031.     var = GetStringVar("AddBoundedControls", object, 
  1032.         k == 2 ? ZNAME : (k ? YNAME : XNAME));
  1033.     if (var)
  1034.     {
  1035.         strcpy(tempStr, GetString(var));
  1036.     }
  1037.     else
  1038.     {
  1039.         strcpy(tempStr, k == 2 ? "Z" : (k ? "Y" : "X"));
  1040.     }
  1041.     textBox = NewTextBox(left, right,
  1042.         mid - EDITBOXHEIGHT / 2,
  1043.         mid + EDITBOXHEIGHT / 2,
  1044.         EDITABLE + WITH_PIT + ONE_LINE,
  1045.         k == 2 ? "Z Axis Name" : (k ? "Y Axis Name" : "X Axis Name"),
  1046.         tempStr); 
  1047.     PrefixList(panelContents, textBox);
  1048.     SetVar(textBox, PARENT, panelContents);
  1049.     SetTextAlign(textBox, RIGHTALIGN);
  1050.     switch (k)
  1051.     {
  1052.         case 0:
  1053.         AssocDirectControlWithVar(textBox, object, XNAME);
  1054.         break;
  1055.         case 1:
  1056.         AssocDirectControlWithVar(textBox, object, YNAME);
  1057.         break;
  1058.         case 2:
  1059.         AssocDirectControlWithVar(textBox, object, ZNAME);
  1060.         break;
  1061.     }
  1062.     SetVar(textBox, HELPSTRING, NewString("This text box contains the name of the \
  1063. indicated axis."));
  1064.     }
  1065.     top = bottom - SBFUNCTIONSPACING;
  1066.  
  1067.     /*Axis name check boxes*/
  1068.     left = MINORBORDER;
  1069.     right = left + SBFUNCTIONNAMEWIDTH;
  1070.     bottom = top - CHECKBOXHEIGHT;
  1071.  
  1072.     textBox = NewTextBox(left, right, 
  1073.             top - TEXTBOXHEIGHT + EDITBOXDOWN,
  1074.             top + EDITBOXDOWN,
  1075.             0, "Show Names Text", "Show Name:"); 
  1076.     PrefixList(panelContents, textBox);
  1077.     SetVar(textBox, PARENT, panelContents);
  1078.  
  1079.     /*Draw name check boxes*/
  1080.     bottom = top - CHECKBOXHEIGHT;
  1081.  
  1082.     curFlag = 1;
  1083.     for (k = 0; k < 3; ++k)
  1084.     {
  1085.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1086.     right = left + rightWidth / 3 - MINORBORDER;
  1087.  
  1088.     checkBox = NewCheckBox(left, right,
  1089.                    bottom, 
  1090.                    top, 
  1091.                    k == 0 ? "Centered" : k == 1 ? "Centered " : "Centered  ",
  1092.                    0);
  1093.     if (!checkBox)
  1094.     {
  1095.         return ObjFalse;
  1096.     }
  1097.         PrefixList(panelContents, checkBox);
  1098.     SetVar(checkBox, PARENT, panelContents);
  1099.     sprintf(tempStr, "If this box is checked, the name of this axis will be shown at the center of the axis.");
  1100.     SetVar(checkBox, HELPSTRING, NewString(tempStr));
  1101.     AssocFlagControlWithVar(checkBox, object, DRAWNAMES, curFlag);
  1102.     curFlag *= 2;
  1103.     }
  1104.     top = bottom - CHECKBOXSPACING;
  1105.  
  1106.     left = MINORBORDER;
  1107.     right = left + SBFUNCTIONNAMEWIDTH;
  1108.     bottom = top - EDITBOXHEIGHT;
  1109.     mid = (bottom + top) / 2;
  1110.     textBox = NewTextBox(left, right, 
  1111.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1112.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1113.             0, "Major Step Text", "Major Step:"); 
  1114.     PrefixList(panelContents, textBox);
  1115.     SetVar(textBox, PARENT, panelContents);
  1116.     left = right;
  1117.  
  1118.     for (k = 0; k < 3; ++k)
  1119.     {
  1120.     /*Make the major step edit box*/
  1121.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1122.     right = left + rightWidth / 3 - MINORBORDER;
  1123.  
  1124.     textBox = NewTextBox(left, right,
  1125.         mid - EDITBOXHEIGHT / 2,
  1126.         mid + EDITBOXHEIGHT / 2,
  1127.         EDITABLE + WITH_PIT + ONE_LINE,
  1128.         k == 2 ? "Z Major Step" : (k ? "Y Major Step" : "X Major Step"),
  1129.         ""); 
  1130.     PrefixList(panelContents, textBox);
  1131.     SetVar(textBox, PARENT, panelContents);
  1132.     SetTextAlign(textBox, RIGHTALIGN);
  1133.     AssocIndexedTextRealControlWithVar(textBox, object, AXISMAJORSTEP, k, 0, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  1134.     SetVar(textBox, HELPSTRING, NewString("This text box contains a number \
  1135. which gives the step size for major tic marks along the indicated dimension.  \
  1136. The major steps are calculated relative to the origin."));
  1137.     }
  1138.     top = bottom - SBFUNCTIONSPACING;
  1139.  
  1140.     left = MINORBORDER;
  1141.     right = left + SBFUNCTIONNAMEWIDTH;
  1142.     bottom = top - EDITBOXHEIGHT;
  1143.     mid = (bottom + top) / 2;
  1144.     textBox = NewTextBox(left, right, 
  1145.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1146.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1147.             0, "Divisions Text", "Divisions:"); 
  1148.     PrefixList(panelContents, textBox);
  1149.     SetVar(textBox, PARENT, panelContents);
  1150.     left = right;
  1151.  
  1152.     for (k = 0; k < 3; ++k)
  1153.     {
  1154.     /*Make the major step edit box*/
  1155.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1156.     right = left + rightWidth / 3 - MINORBORDER;
  1157.  
  1158.     textBox = NewTextBox(left, right,
  1159.         mid - EDITBOXHEIGHT / 2,
  1160.         mid + EDITBOXHEIGHT / 2,
  1161.         EDITABLE + WITH_PIT + ONE_LINE,
  1162.         k == 2 ? "Z Divisions" : (k ? "Y Divisions" : "X Divisions"),
  1163.         ""); 
  1164.     PrefixList(panelContents, textBox);
  1165.     SetVar(textBox, PARENT, panelContents);
  1166.     SetTextAlign(textBox, RIGHTALIGN);
  1167.     AssocIndexedTextRealControlWithVar(textBox, object, AXISDIVISIONS, k, 1, plusInf, TR_INT_ONLY | TR_NE_TOP);
  1168.     SetVar(textBox, HELPSTRING, NewString("This text box contains a number \
  1169. which gives the number of minor divisions within each major step.  For example, if the major step \
  1170. is 1.0, and the number of divisions is 10, there will be a minor tic every 0.1 units."));
  1171.     }
  1172.     top = bottom - SBFUNCTIONSPACING;
  1173.  
  1174.     /*Tic length controls*/
  1175.     left = MINORBORDER;
  1176.     right = left + SBFUNCTIONNAMEWIDTH;
  1177.     bottom = top - EDITBOXHEIGHT;
  1178.     mid = (bottom + top) / 2;
  1179.     textBox = NewTextBox(left, right, 
  1180.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1181.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1182.             0, "Tic Length Text", "Tic Length:"); 
  1183.     PrefixList(panelContents, textBox);
  1184.     SetVar(textBox, PARENT, panelContents);
  1185.     left = right;
  1186.  
  1187.     for (k = 0; k < 3; ++k)
  1188.     {
  1189.     /*Make the tic length box*/
  1190.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1191.     right = left + rightWidth / 3 - MINORBORDER;
  1192.     textBox = NewTextBox(left, right,
  1193.         mid - EDITBOXHEIGHT / 2,
  1194.         mid + EDITBOXHEIGHT / 2,
  1195.         EDITABLE + WITH_PIT + ONE_LINE,
  1196.         k == 2 ? "Z Tic Length" : (k ? "Y Tic Length" : "X Tic Length"),
  1197.         ""); 
  1198.     PrefixList(panelContents, textBox);
  1199.     SetVar(textBox, PARENT, panelContents);
  1200.     SetTextAlign(textBox, RIGHTALIGN);
  1201.     AssocIndexedTextRealControlWithVar(textBox, object, TICLENGTH, k, 0.0, plusInf, 0);
  1202.     SetVar(textBox, HELPSTRING, NewString("This text box contains a number \
  1203. which gives the length of tic marks in the indicated dimension.  The number \
  1204. is in field coordinates."));
  1205.     }
  1206.     top = bottom - SBFUNCTIONSPACING;
  1207.  
  1208.     /*Major tic mark check boxes*/
  1209.     left = MINORBORDER;
  1210.     right = left + SBFUNCTIONNAMEWIDTH;
  1211.     bottom = top - CHECKBOXHEIGHT;
  1212.  
  1213.     textBox = NewTextBox(left, right, 
  1214.             top - TEXTBOXHEIGHT + EDITBOXDOWN,
  1215.             top + EDITBOXDOWN,
  1216.             0, "Tic Marks Text", "Show Tics:"); 
  1217.     PrefixList(panelContents, textBox);
  1218.     SetVar(textBox, PARENT, panelContents);
  1219.  
  1220.     curFlag = BBXMAJOR;
  1221.     for (k = 0; k < 3; ++k)
  1222.     {
  1223.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1224.     right = left + rightWidth / 3 - MINORBORDER;
  1225.  
  1226.     checkBox = NewCheckBox(left, right,
  1227.                    bottom, 
  1228.                    top, 
  1229.                    k == 0 ? "Major" : k == 1 ? "Major " : "Major  ",
  1230.                    0);
  1231.     if (!checkBox)
  1232.     {
  1233.         return ObjFalse;
  1234.     }
  1235.         PrefixList(panelContents, checkBox);
  1236.     SetVar(checkBox, PARENT, panelContents);
  1237.     sprintf(tempStr, "If this box is checked, major tic marks will be shown along the %c axis.", k == 0 ? 'X' : k == 1 ? 'Y' : 'Z');
  1238.     SetVar(checkBox, HELPSTRING, NewString(tempStr));
  1239.     sprintf(tempStr, "If this box is checked, minor tic marks will be shown along the %c axis.", k == 0 ? 'X' : k == 1 ? 'Y' : 'Z');
  1240.     SetVar(checkBox, HELPSTRING, NewString(tempStr));
  1241.     AssocFlagControlWithVar(checkBox, object, BBFLAGS, curFlag);
  1242.     curFlag *= 4;
  1243.     }
  1244.     top = bottom - SBFUNCTIONSPACING;
  1245.  
  1246.     /*Minor tic mark check boxes*/
  1247.     bottom = top - CHECKBOXHEIGHT;
  1248.  
  1249.     curFlag = BBXMINOR;
  1250.     for (k = 0; k < 3; ++k)
  1251.     {
  1252.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1253.     right = left + rightWidth / 3 - MINORBORDER;
  1254.  
  1255.     checkBox = NewCheckBox(left, right,
  1256.                    bottom, 
  1257.                    top, 
  1258.                    k == 0 ? "Minor" : k == 1 ? "Minor " : "Minor  ",
  1259.                    0);
  1260.     if (!checkBox)
  1261.     {
  1262.         return ObjFalse;
  1263.     }
  1264.         PrefixList(panelContents, checkBox);
  1265.     SetVar(checkBox, PARENT, panelContents);
  1266.     sprintf(tempStr, "If this box is checked, minor tic marks will be shown along the %c axis.", k == 0 ? 'X' : k == 1 ? 'Y' : 'Z');
  1267.     SetVar(checkBox, HELPSTRING, NewString(tempStr));
  1268.     AssocFlagControlWithVar(checkBox, object, BBFLAGS, curFlag);
  1269.     curFlag *= 4;
  1270.     }
  1271.     top = bottom - CHECKBOXSPACING;
  1272.  
  1273.     return ObjTrue;
  1274. }
  1275.  
  1276. static ObjPtr AddWallsControls(object, panelContents)
  1277. ObjPtr object, panelContents;
  1278. /*Adds controls for a visualization object with walls*/
  1279. {
  1280.     ObjPtr titleBox, checkBox, textBox;
  1281.     ObjPtr colorWheel, slider;
  1282.     int left, right, bottom, top, width, i, j, whichWall, k, f, h;
  1283.     int l, r, b, t;
  1284.     int titleWidth, buttonWidth;
  1285.     char buttonName[40];
  1286.  
  1287.     width = CWINWIDTH - CORRALBORDER - CWINCORRALWIDTH;
  1288.     left = MINORBORDER;
  1289.     right = width - MINORBORDER;
  1290.     top = CWINHEIGHT - MINORBORDER;
  1291.     bottom = MINORBORDER;
  1292.  
  1293.     buttonWidth = (width - 6 * MINORBORDER) / 4;
  1294.     titleWidth = buttonWidth;
  1295.     titleWidth += 21;
  1296.     buttonWidth -= 7;
  1297.  
  1298.     for (i = 0; i < 3; ++i)
  1299.     {
  1300.     for (j = 0; j < 2; ++j)
  1301.     {
  1302.         k = j + i * 2;
  1303.         
  1304.         f = 1 << k;
  1305.  
  1306.         l = left;
  1307.         r = l + titleWidth;
  1308.         t = top - k * (CHECKBOXHEIGHT + CHECKBOXSPACING);
  1309.         b = t - CHECKBOXHEIGHT;
  1310.  
  1311.         sprintf(buttonName, "%s:", wallNames[k]);
  1312.         textBox = NewTextBox(l, r, b - 4, t - 4, PLAIN, buttonName, buttonName);
  1313.         PrefixList(panelContents, textBox);
  1314.         SetVar(panelContents, PARENT, textBox);
  1315.  
  1316.         l = r + MINORBORDER;
  1317.         r = l + buttonWidth;
  1318.  
  1319.         strcpy(buttonName, "Wall");
  1320.         AppendSpaces(buttonName, k);
  1321.         checkBox = NewCheckBox(l, r, b, t, buttonName, false);
  1322.         PrefixList(panelContents, checkBox);
  1323.         SetVar(checkBox, PARENT, panelContents);
  1324.         AssocFlagControlWithVar(checkBox, object, WALLPANELFLAGS, f);
  1325.         sprintf(tempStr, "When this check box is on, the %s wall is visible.  \
  1326. The Wall Panel, Wall Lines, and Draw control groups at the bottom of the \
  1327. window control how visible walls are drawn.", wallNames[k]);
  1328.         SetVar(checkBox, HELPSTRING, NewString(tempStr));
  1329.        
  1330.         l = r + MINORBORDER;
  1331.         r = l + buttonWidth;
  1332.  
  1333.         strcpy(buttonName, "Shadow");
  1334.         AppendSpaces(buttonName, k);
  1335.         checkBox = NewCheckBox(l, r, b, t, buttonName, false);
  1336.         PrefixList(panelContents, checkBox);
  1337.         SetVar(checkBox, PARENT, panelContents);
  1338.         AssocFlagControlWithVar(checkBox, object, WALLSHADOWFLAGS, f);
  1339.         sprintf(tempStr, "When this check box is on, a black shadown of the \
  1340. visualization is shown on the %s wall.", wallNames[k]);
  1341.         SetVar(checkBox, HELPSTRING, NewString(tempStr));
  1342.         
  1343.         l = r + MINORBORDER;
  1344.         r = l + buttonWidth;
  1345.  
  1346.         strcpy(buttonName, "Mirror");
  1347.         AppendSpaces(buttonName, k);
  1348.         checkBox = NewCheckBox(l, r, b, t, buttonName, false);
  1349.         PrefixList(panelContents, checkBox);
  1350.         SetVar(checkBox, PARENT, panelContents);
  1351.         AssocFlagControlWithVar(checkBox, object, WALLMIRRORFLAGS, f);
  1352.         sprintf(tempStr, "When this check box is on, the %s wall acts as a mirror \
  1353. for the visualization object.  It's not quite like a real mirror, as the presence of the \
  1354. reflection does not depend in any way whether the angle of view included the mirror.  Also, \
  1355. facing mirrors do not produce a barbershop effect.  This feature is useful when only one-half \
  1356. or one-quarter of a problem domain has been computed and you want to display the rest \
  1357. automatically.", wallNames[k]);
  1358.         SetVar(checkBox, HELPSTRING, NewString(tempStr));
  1359.     }
  1360.     }
  1361.  
  1362.     t = top - 6 * (CHECKBOXHEIGHT + CHECKBOXSPACING) - MINORBORDER;
  1363.  
  1364.     /*Make the wall panel control group*/
  1365.     titleBox = NewTitleBox(left, left + 3 * MINORBORDER + COLORWHEELWIDTH + SLIDERWIDTH,
  1366.                t - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT - TITLEBOXTOP - 2 * MINORBORDER,
  1367.                t, "Wall Panels");
  1368.     PrefixList(panelContents, titleBox);
  1369.     SetVar(titleBox, PARENT, panelContents);
  1370.  
  1371.     l = left + MINORBORDER;
  1372.     r = l + COLORWHEELWIDTH;
  1373.     
  1374.     t -= TITLEBOXTOP + MINORBORDER;
  1375.     b = t - COLORWHEELWIDTH;
  1376.  
  1377.     /*Make the color wheel and its text box*/
  1378.     colorWheel = NewColorWheel(l, r, b, t, "Panel Color Wheel");
  1379.     SetVar(colorWheel, PARENT, panelContents);
  1380.     PrefixList(panelContents, colorWheel);
  1381.     AssocColorControlWithVar(colorWheel, object, WALLPANELCOLOR); 
  1382.     SetVar(colorWheel, HELPSTRING, NewString("This color wheel controls the \
  1383. hue and saturation of the color used to draw the panels of visible walls.  \
  1384. The final color is a combination of this hue and saturation and the value, or brightness, \
  1385. given by the Value slider."));
  1386.  
  1387.     textBox = NewTextBox(l, r, b - TEXTBOXSEP - TEXTBOXHEIGHT, b - TEXTBOXSEP,
  1388.         PLAIN, "Panel Color Text", "Color");
  1389.     SetVar(textBox, PARENT, panelContents);
  1390.     PrefixList(panelContents, textBox);
  1391.     SetTextAlign(textBox, CENTERALIGN);
  1392.  
  1393.     l = r + MINORBORDER;
  1394.  
  1395.     r = l + SLIDERWIDTH;
  1396.  
  1397.     /*Make the brightness slider*/
  1398.     slider = NewSlider(l, r, b, t,
  1399.                PLAIN, "Panel Color Value");
  1400.     SetVar(slider, PARENT, panelContents);
  1401.     PrefixList(panelContents, slider);
  1402.     SetSliderRange(slider, 1.0, 0.0, 0.0);
  1403.     AssocBrightnessControlWithVar(slider, object, WALLPANELCOLOR);
  1404.     SetVar(slider, HELPSTRING, NewString("This slider controls the \
  1405. value, or brightness, of the color used to draw panels of visible walls.  \
  1406. The final color is a combination of this value and the hue and saturation \
  1407. given by the Color color wheel."));
  1408.  
  1409.     textBox = NewTextBox(l - MINORBORDER, r + MINORBORDER, b - TEXTBOXSEP - TEXTBOXHEIGHT, b - TEXTBOXSEP,
  1410.         PLAIN, "{ame; Value Text", "Value");
  1411.     SetVar(textBox, PARENT, panelContents);
  1412.     PrefixList(panelContents, textBox);
  1413.     SetTextAlign(textBox, CENTERALIGN);
  1414.  
  1415.     l = r + MINORBORDER;
  1416.  
  1417.     l += MINORBORDER;
  1418.     r = right;
  1419.     t = top - 6 * (CHECKBOXHEIGHT + CHECKBOXSPACING) - MINORBORDER;
  1420.  
  1421.     /*Make the wall lines control group*/
  1422.     titleBox = NewTitleBox(l, l + 3 * MINORBORDER + COLORWHEELWIDTH + SLIDERWIDTH,
  1423.                t - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT - TITLEBOXTOP - 2 * MINORBORDER,
  1424.                t, "Wall Lines");
  1425.     PrefixList(panelContents, titleBox);
  1426.     SetVar(titleBox, PARENT, panelContents);
  1427.  
  1428.     l += MINORBORDER;
  1429.     r -= MINORBORDER;
  1430.     
  1431.     t -= TITLEBOXTOP + MINORBORDER;
  1432.     b = t - COLORWHEELWIDTH;
  1433.     r = l + COLORWHEELWIDTH;
  1434.  
  1435.     /*Make the color wheel and its text box*/
  1436.     colorWheel = NewColorWheel(l, r, b, t, "Panel Lines Color Wheel");
  1437.     SetVar(colorWheel, PARENT, panelContents);
  1438.     PrefixList(panelContents, colorWheel);
  1439.     AssocColorControlWithVar(colorWheel, object, WALLLINESCOLOR); 
  1440.     SetVar(colorWheel, HELPSTRING, NewString("This color wheel controls the \
  1441. hue and saturation of the color used to draw lines on visible walls.  \
  1442. The final color is a combination of this hue and saturation and the value, or brightness, \
  1443. given by the Value slider."));
  1444.  
  1445.     textBox = NewTextBox(l, r, b - TEXTBOXSEP - TEXTBOXHEIGHT, b - TEXTBOXSEP,
  1446.         PLAIN, "Wall Lines Color Text", "Color");
  1447.     SetVar(textBox, PARENT, panelContents);
  1448.     PrefixList(panelContents, textBox);
  1449.     SetTextAlign(textBox, CENTERALIGN);
  1450.  
  1451.     l = r + MINORBORDER;
  1452.  
  1453.     r = l + SLIDERWIDTH;
  1454.  
  1455.     /*Make the brightness slider*/
  1456.     slider = NewSlider(l, r, b, t,
  1457.                PLAIN, "Wall Lines Color Value");
  1458.     SetVar(slider, PARENT, panelContents);
  1459.     PrefixList(panelContents, slider);
  1460.     SetSliderRange(slider, 1.0, 0.0, 0.0);
  1461.     AssocBrightnessControlWithVar(slider, object, WALLLINESCOLOR);
  1462.     SetVar(slider, HELPSTRING, NewString("This slider controls the \
  1463. value, or brightness, of the color used to draw lines on visible walls.  \
  1464. The final color is a combination of this value and the hue and saturation \
  1465. given by the Color color wheel."));
  1466.  
  1467.     textBox = NewTextBox(l - MINORBORDER, r + MINORBORDER, b - TEXTBOXSEP - TEXTBOXHEIGHT, b - TEXTBOXSEP,
  1468.         PLAIN, "Wall Lines Value Text", "Value");
  1469.     SetVar(textBox, PARENT, panelContents);
  1470.     PrefixList(panelContents, textBox);
  1471.     SetTextAlign(textBox, CENTERALIGN);
  1472.  
  1473.     /*Put in the draw checkBoxs at the right*/
  1474.  
  1475.     l = r + 2 * MINORBORDER;
  1476.     r = right;
  1477.     t = t + MINORBORDER + TITLEBOXTOP;
  1478.     b = b - MINORBORDER - TEXTBOXHEIGHT - TEXTBOXSEP;
  1479.  
  1480.     titleBox = NewTitleBox(l, r, b, t, "Draw");
  1481.     SetVar(titleBox, PARENT, panelContents);
  1482.     PrefixList(panelContents, titleBox);
  1483.  
  1484.     l += MINORBORDER;
  1485.     t -= TITLEBOXTOP + MINORBORDER;
  1486.     r -= MINORBORDER;
  1487.  
  1488.     b = t - CHECKBOXHEIGHT;
  1489.     checkBox = NewCheckBox(l, r, b, t, "Outline", 
  1490.         GetPredicate(object, DRAWOUTLINE));
  1491.     SetVar(checkBox, PARENT, panelContents);
  1492.     PrefixList(panelContents, checkBox);
  1493.     AssocDirectControlWithVar(checkBox, object, DRAWOUTLINE);
  1494.     SetVar(checkBox, HELPSTRING, 
  1495.     NewString("This check box controls the drawing of the outline of visible walls.  \
  1496. When it is on, an outline is drawn around every one of the visible walls.  \
  1497. When it is off, the outline is not drawn.  The color is \
  1498. given by the Wall Lines controls, and other parameters of the lines such as width and \
  1499. antialiasing are set in the Lines control panel.  Unlike the wall panel, the outline \
  1500. is visible even when viewed from the outside."));
  1501.     t = b - CHECKBOXSPACING;
  1502.  
  1503.     b = t - CHECKBOXHEIGHT;
  1504.     checkBox = NewCheckBox(l, r, b, t, "Grid", 
  1505.         GetPredicate(object, DRAWGRID));
  1506.     SetVar(checkBox, PARENT, panelContents);
  1507.     PrefixList(panelContents, checkBox);
  1508.     AssocDirectControlWithVar(checkBox, object, DRAWGRID);
  1509.     SetVar(checkBox, HELPSTRING, 
  1510.     NewString("This check box controls the drawing of a grid on visible walls.  \
  1511. When it is on, a grid is drawn on every one of the visible walls.  \
  1512. The spacing of the grid is given on the major tic marks as defined in \
  1513. the Axes control panel.  When the check box is off, the grid is not drawn.  The color is \
  1514. given by the Wall Lines controls, and other parameters of the lines such as width and \
  1515. antialiasing are set in the Lines control panel.  Unlike the wall panel, the grid \
  1516. is visible even when viewed from the outside."));
  1517.     t = b - CHECKBOXSPACING;
  1518.  
  1519.     b = t - CHECKBOXHEIGHT;
  1520.     checkBox = NewCheckBox(l, r, b, t, "Panel", 
  1521.         GetPredicate(object, DRAWBACKGROUND));
  1522.     SetVar(checkBox, PARENT, panelContents);
  1523.     PrefixList(panelContents, checkBox);
  1524.     AssocDirectControlWithVar(checkBox, object, DRAWBACKGROUND);
  1525.     SetVar(checkBox, HELPSTRING, 
  1526.     NewString("This check box controls the drawing of panels on visible walls.  \
  1527. When it is on, a solid, shaded panel is drawn for every one of the visible walls.  \
  1528. When it is off, the background is not drawn.  Panels, \
  1529. like shadows, are only visible when viewed from the inside.  The color of \
  1530. the panel is given by the Wall Panels color wheel and value slider."));
  1531.     t = b - CHECKBOXSPACING;
  1532.  
  1533.     b = t - CHECKBOXHEIGHT;
  1534.  
  1535.     return ObjTrue;
  1536. }
  1537.  
  1538. static ObjPtr AddBoundedControls(object, panelContents)
  1539. ObjPtr object, panelContents;
  1540. /*Adds controls for a visualization object with a bounding box*/
  1541. {
  1542.     int width;
  1543.     int left, top, right, mid, bottom, rightWidth;
  1544.     ObjPtr checkBox, titleBox, textBox;
  1545.     ObjPtr flagsObj, var;
  1546.     int flags;
  1547.     int curFlag;
  1548.     int i, j, k;
  1549.     int tbh;
  1550.     real bounds[6];
  1551.  
  1552.     width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
  1553.     left = MINORBORDER;
  1554.     top = CWINHEIGHT - MAJORBORDER;
  1555.  
  1556.     flagsObj = GetVar(object, BBFLAGS);
  1557.     if (flagsObj)
  1558.     {
  1559.     flags = GetInt(flagsObj);
  1560.     }
  1561.     else
  1562.     {
  1563.     flags = 0;
  1564.     }
  1565.  
  1566.     GetBounds(object, bounds);
  1567.  
  1568.     /*Make control group, from top to bottom*/
  1569.  
  1570.     top = CWINHEIGHT - MINORBORDER;
  1571.     rightWidth = (width - MINORBORDER - SBFUNCTIONNAMEWIDTH);
  1572.  
  1573.     /*Axis name edit boxes*/
  1574.     MakeVar(object, XNAME);
  1575.     MakeVar(object, YNAME);
  1576.     MakeVar(object, ZNAME);
  1577.  
  1578.     left = MINORBORDER;
  1579.     right = left + SBFUNCTIONNAMEWIDTH;
  1580.     bottom = top -  EDITBOXHEIGHT;
  1581.     mid = (bottom + top) / 2;
  1582.     textBox = NewTextBox(left, right, 
  1583.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1584.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1585.             0, "Axis Name Text", "Axis Name:"); 
  1586.     PrefixList(panelContents, textBox);
  1587.     SetVar(textBox, PARENT, panelContents);
  1588.     left = right;
  1589.  
  1590.     for (k = 0; k < 3; ++k)
  1591.     {
  1592.     /*Make the axis edit box*/
  1593.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1594.     right = left + rightWidth / 3 - MINORBORDER;
  1595.  
  1596.     var = GetStringVar("AddBoundedControls", object, 
  1597.         k == 2 ? ZNAME : (k ? YNAME : XNAME));
  1598.     if (var)
  1599.     {
  1600.         strcpy(tempStr, GetString(var));
  1601.     }
  1602.     else
  1603.     {
  1604.         strcpy(tempStr, k == 2 ? "Z" : (k ? "Y" : "X"));
  1605.     }
  1606.     textBox = NewTextBox(left, right,
  1607.         mid - EDITBOXHEIGHT / 2,
  1608.         mid + EDITBOXHEIGHT / 2,
  1609.         EDITABLE + WITH_PIT + ONE_LINE,
  1610.         k == 2 ? "Z Axis Name" : (k ? "Y Axis Name" : "X Axis Name"),
  1611.         tempStr); 
  1612.     PrefixList(panelContents, textBox);
  1613.     SetVar(textBox, PARENT, panelContents);
  1614.     SetTextAlign(textBox, RIGHTALIGN);
  1615.     switch (k)
  1616.     {
  1617.         case 0:
  1618.         AssocDirectControlWithVar(textBox, object, XNAME);
  1619.         break;
  1620.         case 1:
  1621.         AssocDirectControlWithVar(textBox, object, YNAME);
  1622.         break;
  1623.         case 2:
  1624.         AssocDirectControlWithVar(textBox, object, ZNAME);
  1625.         break;
  1626.     }
  1627.     SetVar(textBox, HELPSTRING, NewString("This text box contains the name of the \
  1628. indicated axis.  This is the name displayed when Axis Names box is checked."));
  1629.     }
  1630.     top = bottom - SBFUNCTIONSPACING;
  1631.  
  1632.     /*Min edit boxes*/
  1633.     left = MINORBORDER;
  1634.     right = left + SBFUNCTIONNAMEWIDTH;
  1635.     bottom =top - EDITBOXHEIGHT;
  1636.     mid = (bottom + top) / 2;
  1637.     textBox = NewTextBox(left, right, 
  1638.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1639.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1640.             0, "Minimum Text", "Minimum:"); 
  1641.     PrefixList(panelContents, textBox);
  1642.     SetVar(textBox, PARENT, panelContents);
  1643.     left = right;
  1644.  
  1645.     for (k = 0; k < 3; ++k)
  1646.     {
  1647.     /*Make the minimum edit box*/
  1648.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1649.     right = left + rightWidth / 3 - MINORBORDER;
  1650.  
  1651.     PrintNumber(tempStr, bounds[k * 2]);
  1652.     textBox = NewTextBox(left, right,
  1653.         mid - EDITBOXHEIGHT / 2,
  1654.         mid + EDITBOXHEIGHT / 2,
  1655.         EDITABLE + WITH_PIT + ONE_LINE,
  1656.         k == 2 ? "Z Minimum" : (k ? "Y Minimum" : "X Minimum"),
  1657.         tempStr); 
  1658.     PrefixList(panelContents, textBox);
  1659.     SetVar(textBox, PARENT, panelContents);
  1660.     SetTextAlign(textBox, RIGHTALIGN);
  1661.     AssocIndexedTextRealControlWithVar(textBox, object, BOUNDS, k * 2, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  1662.     SetVar(textBox, HELPSTRING, NewString("This text box contains a number \
  1663. which gives the minimum value of the bounds in the indicated dimension.  Change \
  1664. this number to change the bounds.  The number must not be greater than the \
  1665. maximum."));
  1666.     }
  1667.     top = bottom - SBFUNCTIONSPACING;
  1668.  
  1669.     /*Max edit boxes*/
  1670.     left = MINORBORDER;
  1671.     right = left + SBFUNCTIONNAMEWIDTH;
  1672.     bottom = top - EDITBOXHEIGHT;
  1673.     mid = (bottom + top) / 2;
  1674.     textBox = NewTextBox(left, right, 
  1675.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1676.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1677.             0, "Maximum Text", "Maximum:"); 
  1678.     PrefixList(panelContents, textBox);
  1679.     SetVar(textBox, PARENT, panelContents);
  1680.     left = right;
  1681.  
  1682.     for (k = 0; k < 3; ++k)
  1683.     {
  1684.     /*Make the maximum edit box*/
  1685.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1686.     right = left + rightWidth / 3 - MINORBORDER;
  1687.  
  1688.     PrintNumber(tempStr, bounds[k * 2 + 1]);
  1689.     textBox = NewTextBox(left, right,
  1690.         mid - EDITBOXHEIGHT / 2,
  1691.         mid + EDITBOXHEIGHT / 2,
  1692.         EDITABLE + WITH_PIT + ONE_LINE,
  1693.         k == 2 ? "Z Maximum" : (k ? "Y Maximum" : "X Maximum"),
  1694.         tempStr); 
  1695.     PrefixList(panelContents, textBox);
  1696.     SetVar(textBox, PARENT, panelContents);
  1697.     SetTextAlign(textBox, RIGHTALIGN);
  1698.     AssocIndexedTextRealControlWithVar(textBox, object, BOUNDS, k * 2 + 1, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  1699.     SetVar(textBox, HELPSTRING, NewString("This text box contains a number \
  1700. which gives the maximum value of the bounds in the indicated dimension.  Change \
  1701. this number to change the bounds.  The number must not be less than the \
  1702. minimum."));
  1703.     }
  1704.     top = bottom - SBFUNCTIONSPACING;
  1705.  
  1706.     /*Axis scaling edit boxes*/
  1707.     MakeVar(object, XSCALE);
  1708.     MakeVar(object, YSCALE);
  1709.     MakeVar(object, ZSCALE);
  1710.  
  1711.     left = MINORBORDER;
  1712.     right = left + SBFUNCTIONNAMEWIDTH;
  1713.     bottom = top - EDITBOXHEIGHT;
  1714.     mid = (bottom + top) / 2;
  1715.     textBox = NewTextBox(left, right, 
  1716.             mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1717.             mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  1718.             0, "Axis Scaling Text", "Scaling:"); 
  1719.     PrefixList(panelContents, textBox);
  1720.     SetVar(textBox, PARENT, panelContents);
  1721.     left = right;
  1722.  
  1723.     for (k = 0; k < 3; ++k)
  1724.     {
  1725.     /*Make the axis edit box*/
  1726.     left = 2 * MINORBORDER + SBFUNCTIONNAMEWIDTH + k * rightWidth / 3;
  1727.     right = left + rightWidth / 3 - MINORBORDER;
  1728.  
  1729.     var = GetRealVar("AddBoundedControls", object, 
  1730.         k == 2 ? ZSCALE : (k ? YSCALE : XSCALE));
  1731.     if (var)
  1732.     {
  1733.         PrintNumber(tempStr, GetReal(var));
  1734.     }
  1735.     else
  1736.     {
  1737.         strcpy(tempStr, "1");
  1738.     }
  1739.     textBox = NewTextBox(left, right,
  1740.         mid - EDITBOXHEIGHT / 2,
  1741.         mid + EDITBOXHEIGHT / 2,
  1742.         EDITABLE + WITH_PIT + ONE_LINE,
  1743.         k == 2 ? "Z Axis Scaling" : (k ? "Y Axis Scaling" : "X Axis Scaling"),
  1744.         tempStr); 
  1745.     PrefixList(panelContents, textBox);
  1746.     SetVar(textBox, PARENT, panelContents);
  1747.     SetTextAlign(textBox, RIGHTALIGN);
  1748.     switch (k)
  1749.     {
  1750.         case 0:
  1751.         AssocTextRealControlWithVar(textBox, object, XSCALE, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  1752.         break;
  1753.         case 1:
  1754.         AssocTextRealControlWithVar(textBox, object, YSCALE, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  1755.         break;
  1756.         case 2:
  1757.         AssocTextRealControlWithVar(textBox, object, ZSCALE, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  1758.         break;
  1759.     }
  1760.     SetVar(textBox, HELPSTRING, NewString("This text box contains the scaling \
  1761. of the selected axis.  Normally, all three axes are scaled at 1, indicating that \
  1762. all three axes have the same units.  However, sometimes it is useful to use different \
  1763. scales.\n\nFor example, say you have a mesh of terrain.  The X and Y coordinates are \
  1764. in kilometers, but the Z coordinate is in meters.  To make the visualization appear \
  1765. accurately, you might make the X and Y scaling 1000 while keeping the Z scaling at 1."));
  1766.     }
  1767.     top = bottom - SBFUNCTIONSPACING;
  1768.  
  1769.     return ObjTrue;
  1770. }
  1771.  
  1772. static ObjPtr DropInColorCorral(corral, object, x, y)
  1773. ObjPtr corral, object;
  1774. int x, y;
  1775. /*Drops an icon in a field corral*/
  1776. {
  1777.     ObjPtr visObj;
  1778.     ObjPtr fieldObj;
  1779.     ObjPtr icon;
  1780.     ObjPtr name;
  1781.     ObjPtr defaultIcon;
  1782.     ObjPtr contents;
  1783.     ObjPtr button;
  1784.     long info;
  1785.  
  1786.     /*Find the visualization object*/
  1787.     visObj = GetObjectVar("DropInColorCorral", corral, REPOBJ);
  1788.     if (!visObj)
  1789.     {
  1790.     return ObjFalse;
  1791.     }
  1792.  
  1793.     /*Get the field object*/
  1794.     fieldObj = GetObjectVar("DropInColorCorral", object, REPOBJ);
  1795.     if (!fieldObj)
  1796.     {
  1797.     return ObjFalse;
  1798.     }
  1799.  
  1800.     info = GetDatasetInfo(fieldObj);
  1801.     if ((info & DS_HASGEOMETRY) && (fieldObj != GetVar(visObj, MAINDATASET)))
  1802.     {
  1803.     WarnUser(CW_NOGEOMETRYERROR);
  1804.     return ObjFalse;
  1805.     }
  1806.  
  1807.     /*Create an icon for it*/
  1808.     name = GetStringVar("DropInColorCorral", fieldObj, NAME);
  1809.     if (!name)
  1810.     {
  1811.     return ObjFalse;
  1812.     }
  1813.  
  1814.     defaultIcon = GetVar(fieldObj, DEFAULTICON);
  1815.     if (defaultIcon)
  1816.     {
  1817.     ObjPtr locArray;
  1818.     real loc[2];
  1819.     icon = NewObject(defaultIcon, 0);
  1820.     SetVar(icon, NAME, name);
  1821.     loc[0] = x;
  1822.     loc[1] = y;
  1823.     locArray = NewRealArray(1, 2L);
  1824.     CArray2Array(locArray, loc);
  1825.     SetVar(icon, ICONLOC, locArray);
  1826.     }
  1827.     else
  1828.     {
  1829.     icon = NewIcon(x, y, ICONQUESTION, GetString(name));
  1830.     }
  1831.     
  1832.     /*Make the icon point to the field*/
  1833.     SetVar(icon, REPOBJ, fieldObj);
  1834.  
  1835.     /*Make it the only icon in the corral*/
  1836.     contents = NewList();
  1837.     PrefixList(contents, icon);
  1838.     SetVar(corral, CONTENTS, contents);
  1839.     SetVar(contents, PARENT, corral);
  1840.     SetVar(icon, PARENT, corral);
  1841.     RecalcScroll(corral);
  1842.  
  1843.     /*Make this object the colored object*/
  1844.     SetVar(visObj, COLOROBJ, fieldObj);
  1845.  
  1846.     /*Activate the show palette button*/
  1847.     button = GetObjectVar("DropInColorCorral", corral, BUTTON);
  1848.     if (button)
  1849.     {
  1850.     ActivateButton(button, true);
  1851.     }
  1852.  
  1853.     ImInvalid(visObj);
  1854.     ImInvalid(corral);
  1855.     return ObjTrue;
  1856. }
  1857.  
  1858. static ObjPtr DropInDeformCorral(corral, object, x, y)
  1859. ObjPtr corral, object;
  1860. int x, y;
  1861. /*Drops an icon in a deformation corral*/
  1862. {
  1863.     ObjPtr visObj;
  1864.     ObjPtr fieldObj;
  1865.     ObjPtr icon;
  1866.     ObjPtr name;
  1867.     ObjPtr defaultIcon;
  1868.     ObjPtr contents;
  1869.     ObjPtr button;
  1870.     long info;
  1871.  
  1872.     /*Find the visualization object*/
  1873.     visObj = GetObjectVar("DropInDeformCorral", corral, REPOBJ);
  1874.     if (!visObj)
  1875.     {
  1876.     return ObjFalse;
  1877.     }
  1878.  
  1879.     /*Get the field object*/
  1880.     fieldObj = GetObjectVar("DropInDeformCorral", object, REPOBJ);
  1881.     if (!fieldObj)
  1882.     {
  1883.     return ObjFalse;
  1884.     }
  1885.  
  1886.     info = GetDatasetInfo(fieldObj);
  1887.     if ((info & DS_HASGEOMETRY))
  1888.     {
  1889.     WarnUser(CW_NOGEOMETRYERROR);
  1890.     return ObjFalse;
  1891.     }
  1892.  
  1893.     /*Create an icon for it*/
  1894.     name = GetStringVar("DropInDeformCorral", fieldObj, NAME);
  1895.     if (!name)
  1896.     {
  1897.     return ObjFalse;
  1898.     }
  1899.  
  1900.     defaultIcon = GetVar(fieldObj, DEFAULTICON);
  1901.     if (defaultIcon)
  1902.     {
  1903.     ObjPtr locArray;
  1904.     real loc[2];
  1905.     icon = NewObject(defaultIcon, 0);
  1906.     SetVar(icon, NAME, name);
  1907.     loc[0] = x;
  1908.     loc[1] = y;
  1909.     locArray = NewRealArray(1, 2L);
  1910.     CArray2Array(locArray, loc);
  1911.     SetVar(icon, ICONLOC, locArray);
  1912.     }
  1913.     else
  1914.     {
  1915.     icon = NewIcon(x, y, ICONQUESTION, GetString(name));
  1916.     }
  1917.     
  1918.     /*Make the icon point to the field*/
  1919.     SetVar(icon, REPOBJ, fieldObj);
  1920.  
  1921.     /*Make it the only icon in the corral*/
  1922.     contents = NewList();
  1923.     PrefixList(contents, icon);
  1924.     SetVar(corral, CONTENTS, contents);
  1925.     SetVar(contents, PARENT, corral);
  1926.     SetVar(icon, PARENT, corral);
  1927.     RecalcScroll(corral);
  1928.  
  1929.     /*Make this object the deformed object*/
  1930.     SetVar(visObj, DEFORMOBJ, fieldObj);
  1931.  
  1932.     ImInvalid(visObj);
  1933.     ImInvalid(corral);
  1934.     return ObjTrue;
  1935. }
  1936.  
  1937. static ObjPtr AddColoredControls(object, panelContents)
  1938. ObjPtr object, panelContents;
  1939. /*Adds controls appropriate to a colored object to panelContents*/
  1940. {
  1941.     ObjPtr control, button, checkBox, corral, sw, textBox, slider, icon, radioGroup;
  1942.     ObjPtr colorObj, titleBox, win;
  1943.     ObjPtr var;
  1944.     int width, left, right, top, cellHeight, m1, m2;
  1945.     ObjPtr parent;
  1946.  
  1947.     /*Get the parent*/
  1948.     parent = GetObjectVar("AddColoredControls", panelContents, PARENT);
  1949.  
  1950.     width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
  1951.     left = MAJORBORDER;
  1952.  
  1953.     cellHeight = MAX(COLORWHEELWIDTH, ONECORRALHEIGHT) - 10;
  1954.  
  1955.     /*Precalculate the midlines for convenience*/
  1956.     m1 = CWINHEIGHT - MAJORBORDER - cellHeight / 2;
  1957.     m1 += MINORBORDER;
  1958.     m2 = m1 - cellHeight - MAJORBORDER - TEXTBOXHEIGHT - TEXTBOXSEP;
  1959.  
  1960.     /*Create the color source corral*/
  1961.     corral = NewIconCorral(NULLOBJ,
  1962.                left, left + ONECORRALWIDTH,
  1963.                m2 - ONECORRALHEIGHT / 2,
  1964.                m2 + ONECORRALHEIGHT / 2, 0);
  1965.     SetVar(corral, SINGLECORRAL, ObjTrue);
  1966.     SetVar(corral, TOPDOWN, ObjTrue);
  1967.     SetVar(corral, NAME, NewString("Color Field"));
  1968.     PrefixList(panelContents, corral);
  1969.     SetVar(corral, HELPSTRING,
  1970.     NewString("This corral shows the dataset that is used to give \
  1971. the visualization object its color, according to the position of the color switch.  \
  1972. To replace it with another dataset, drag the icon of the other \
  1973. dataset into this corral."));
  1974.     SetVar(corral, PARENT, panelContents);
  1975.     SetVar(corral, REPOBJ, object);
  1976.     SetMethod(corral, DROPINCONTENTS, DropInColorCorral);
  1977.  
  1978.     /*Create the color source text box*/
  1979.     textBox = NewTextBox(left, left + ONECORRALWIDTH, 
  1980.              m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP - TEXTBOXHEIGHT,
  1981.              m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP,
  1982.              0, "Color Field Text", "Color Field");
  1983.     PrefixList(panelContents, textBox);
  1984.     SetVar(textBox, PARENT, panelContents);
  1985.     SetTextAlign(textBox, CENTERALIGN);
  1986.  
  1987.     /*Create the show palette button*/
  1988.     win = parent;
  1989.     while (win && !IsWindow(win))
  1990.     {
  1991.     win = GetVar(win, PARENT);
  1992.     }
  1993.     button = NewFunctionButton((WinInfoPtr) win, left, left + ONECORRALWIDTH,
  1994.             m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP - TEXTBOXHEIGHT - MINORBORDER - BUTTONHEIGHT,
  1995.             m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP - TEXTBOXHEIGHT - MINORBORDER,
  1996.             OF_EDIT_PALETTE);
  1997.     PrefixList(panelContents, button);
  1998.     SetVar(button, PARENT, panelContents);
  1999.     SetVar(corral, BUTTON, button);
  2000.     SetVar(button, REPOBJ, corral);
  2001.     SetVar(button, HELPSTRING,
  2002.     NewString("This button shows the palette of the field in the color \
  2003. corral.  First select the icon in the color corral and then press this button.  \
  2004. A new window will appear showing the palette controls."));
  2005.  
  2006.     left += ONECORRALWIDTH + MINORBORDER;
  2007.     colorObj = GetVar(object, COLOROBJ);
  2008.     if (colorObj)
  2009.     {
  2010.     ObjPtr name, defaultIcon;
  2011.     /*Drop icon in corral, if need be*/
  2012.     name = GetVar(colorObj, NAME);
  2013.     defaultIcon = GetVar(colorObj, DEFAULTICON);
  2014.     if (defaultIcon)
  2015.     {
  2016.         icon = NewObject(defaultIcon, 0);
  2017.         SetVar(icon, NAME, name);
  2018.     }
  2019.     else
  2020.     {
  2021.         icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
  2022.         }
  2023.     SetVar(icon, REPOBJ, colorObj);
  2024.     SetVar(icon, ICONLOC, NULLOBJ);
  2025.         DropIconInCorral(corral, icon);
  2026.     }
  2027.     else
  2028.     {
  2029.     ActivateButton(button, false);
  2030.     }
  2031.  
  2032.  
  2033.     /*Create the color control*/
  2034.     control = NewColorWheel(left - COLORWHEELWIDTH - MINORBORDER, left - MINORBORDER, 
  2035.             m1 - COLORWHEELWIDTH / 2,
  2036.             m1 + COLORWHEELWIDTH / 2, "Fixed Color");
  2037.     PrefixList(panelContents, control);
  2038.     SetVar(control, PARENT, panelContents);
  2039.     SetVar(control, REPOBJ, object);
  2040.     SetVar(control, HELPSTRING, NewString("This color wheel controls the base color of a \
  2041. visualization object.  If the window is in full color mode and the object is light shaded, the \
  2042. final color of the object also depends on the lighting."));
  2043.  
  2044.     var = GetFixedArrayVar("AddColoredControls", object, BASECOLOR, 1, 3L);
  2045.     if (!var)
  2046.     {
  2047.     real *baseColor;
  2048.  
  2049.     var = NewRealArray(1, 3L);
  2050.     baseColor = ELEMENTS(var);
  2051.     
  2052.     baseColor[0] = 1.0;
  2053.     baseColor[1] = 1.0;
  2054.     baseColor[2] = 1.0;
  2055.  
  2056.     SetVar(object, BASECOLOR, var);
  2057.     }
  2058.     AssocColorControlWithVar(control, object, BASECOLOR);
  2059.  
  2060.     /*Create the text box*/
  2061.     textBox = NewTextBox(left - COLORWHEELWIDTH - MINORBORDER - 30, left - MINORBORDER + 30, 
  2062.              m1 - cellHeight / 2 - TEXTBOXSEP - TEXTBOXHEIGHT,
  2063.              m1 - cellHeight / 2 - TEXTBOXSEP,
  2064.              0, "Fixed Color Text", "Fixed Color");
  2065.     PrefixList(panelContents, textBox);
  2066.     SetVar(textBox, PARENT, panelContents);
  2067.     SetTextAlign(textBox, CENTERALIGN);
  2068.  
  2069.     /*Create the choice switch*/
  2070.     sw = NewSwitch(left, left + SWITCHWIDTH,
  2071.             m2 - cellHeight / 2 - (MAJORBORDER + TEXTBOXHEIGHT + TEXTBOXSEP) / 2,
  2072.             m1 + cellHeight / 2 + (MAJORBORDER + TEXTBOXHEIGHT + TEXTBOXSEP) / 2,
  2073.             2, 0, GetVar(object, COLORS) ? 1 : 0,
  2074.             "Color Switch");
  2075.     PrefixList(panelContents, sw);
  2076.     SetVar(sw, PARENT, panelContents);
  2077.     SetVar(sw, REPOBJ, object);
  2078.     SetVar(sw, HELPSTRING, NewString("This switch controls whether the color for the visualization object comes from a \
  2079. fixed color or from a field.  The color is passed through a brightness control \
  2080. to produce the base color for the object.\n"));
  2081.     /*Link it to color wheel*/
  2082.     SetVar(control, OTHERSWITCH, sw);
  2083.  
  2084.  
  2085.     /*Set change method*/
  2086.     if (!GetVarSurely("AddColoredControls", object, COLORS))
  2087.     {
  2088.     SetVar(object, COLORS, NewInt(0));
  2089.     }
  2090.     AssocDirectControlWithVar(sw, object, COLORS);
  2091.  
  2092.     left += SWITCHWIDTH + MINORBORDER;
  2093.  
  2094.     /*Create the brightness slider*/
  2095.     var = GetRealVar("AddColoredControls", object, BRIGHTNESS);
  2096.     if (!var)
  2097.     {
  2098.     SetVar(object, BRIGHTNESS, NewReal(1.0));
  2099.     }
  2100.  
  2101.     slider = NewSlider(left, left + SLIDERWIDTH, 
  2102.                m1 - cellHeight / 2, m1 + cellHeight / 2,
  2103.                PLAIN, "Brightness");
  2104.     if (!slider)
  2105.     {
  2106.     return ObjFalse;
  2107.     }
  2108.     PrefixList(panelContents, slider);
  2109.     SetVar(slider, PARENT, panelContents);
  2110.     SetVar(slider, HELPSTRING, NewString("This slider controls the brightness of \
  2111. a visualization object.  Move the indicator up to make the object brighter or down \
  2112. to make it dimmer.  If the object is lit, the eventual brightness will also depend \
  2113. on the lighting."));
  2114.     SetSliderRange(slider, 1.0, 0.0, 0.0);
  2115.     AssocDirectControlWithVar(slider, object, BRIGHTNESS);
  2116.  
  2117.     /*Create the brightness text box*/
  2118.     textBox = NewTextBox(left - MAJORBORDER - MINORBORDER, left + SLIDERWIDTH + MAJORBORDER + MINORBORDER, 
  2119.              m1 - cellHeight / 2 - TEXTBOXSEP - TEXTBOXHEIGHT,
  2120.              m1 - cellHeight / 2 - TEXTBOXSEP,
  2121.              0, "Brightness Text", "Brightness");
  2122.     PrefixList(panelContents, textBox);
  2123.     SetVar(textBox, PARENT, panelContents);
  2124.     SetTextAlign(textBox, CENTERALIGN);
  2125.  
  2126.     left += SLIDERWIDTH + MAJORBORDER;
  2127.  
  2128.     /*Create the unit switch*/
  2129.     sw = NewSwitch(left, left + SSWITCHWIDTH,
  2130.                m1 - cellHeight / 2,
  2131.                m1 + cellHeight / 2,
  2132.                1, 0, 0, "Unit Switch");
  2133.     PrefixList(panelContents, sw);
  2134.     SetVar(sw, PARENT, panelContents);
  2135.     SetVar(sw, HELPSTRING, NewString("This switch shows that the color that has passed through \
  2136. the brightness control is used to produce the base color of the object.\n"));
  2137.     left += SSWITCHWIDTH + MINORBORDER;
  2138.  
  2139.     /*Create the color icon*/
  2140.     icon = NewIcon(left + MINORBORDER + ICONSIZE / 2, m1,
  2141.            ICONCOLOR, "Base Color");
  2142.     PrefixList(panelContents, icon);
  2143.     SetVar(icon, PARENT, panelContents);
  2144.     SetMethod(icon, PRESS, (FuncTyp) 0);
  2145.  
  2146.     left = width - MAJORBORDER - TRANSPARENTWIDTH;
  2147.  
  2148.     /*Create the translucent check box, or use the existing one*/
  2149.     if (checkBox = GetVar(parent, TRANSLUCENTCNT))
  2150.     {
  2151.     PrefixList(panelContents, checkBox);
  2152.     }
  2153.     else
  2154.     {
  2155.     checkBox = NewCheckBox(left, width, 
  2156.         MAJORBORDER + CHECKBOXSPACING + CHECKBOXHEIGHT,
  2157.         MAJORBORDER + CHECKBOXSPACING + 2 * CHECKBOXHEIGHT, "Translucent", GetPredicate(object, ISTRANSLUCENT));
  2158.     if (!checkBox)
  2159.     {
  2160.         return ObjFalse;
  2161.     }
  2162.     PrefixList(panelContents, checkBox);
  2163.     SetVar(checkBox, HELPSTRING,
  2164.         NewString("If this box is checked, the visualization object will be drawn using screen door translucency."));
  2165.     SetVar(checkBox, PARENT, parent);
  2166.     if (!GetVar(object, ISTRANSLUCENT))
  2167.     {
  2168.         SetVar(object, ISTRANSLUCENT, ObjFalse);
  2169.     }
  2170.     AssocDirectControlWithVar(checkBox, object, ISTRANSLUCENT);
  2171.     SetVar(parent, TRANSLUCENTCNT, checkBox);
  2172.     }
  2173.  
  2174.     /*Create the transparent check box, or use the existing one*/
  2175.     if (checkBox = GetVar(parent, TRANSPARENTCNT))
  2176.     {
  2177.     PrefixList(panelContents, checkBox);
  2178.     }
  2179.     else
  2180.     {
  2181.     checkBox = NewCheckBox(left, width, 
  2182.         MAJORBORDER,
  2183.         MAJORBORDER + CHECKBOXHEIGHT, "Transparent", GetPredicate(object, ISTRANSPARENT));
  2184.     if (!checkBox)
  2185.     {
  2186.         return ObjFalse;
  2187.     }
  2188.     PrefixList(panelContents, checkBox);
  2189.     SetVar(checkBox, HELPSTRING,
  2190.         NewString("If this box is checked, the visualization object will be drawn using alpha transparency.  \
  2191. It may be useful to turn down the brightness of the object when using this feature.  Transparency \
  2192. only works on hardware that supports blending transparency.  If you don't \
  2193. have this hardware, try translucency instead."));
  2194.     SetVar(checkBox, PARENT, parent);
  2195.     if (!GetVar(object, ISTRANSPARENT))
  2196.     {
  2197.         SetVar(object, ISTRANSPARENT, ObjFalse);
  2198.     }
  2199.     AssocDirectControlWithVar(checkBox, object, ISTRANSPARENT);
  2200.     SetVar(parent, TRANSPARENTCNT, checkBox);
  2201.  
  2202. #ifdef GRAPHICS
  2203.     if (!hasTransparency) ActivateButton(checkBox, false);
  2204. #endif
  2205.     }
  2206.  
  2207.     /*Create radio button group for color shading*/
  2208.     right = width - MAJORBORDER;
  2209.     top = MAJORBORDER + CHECKBOXHEIGHT * 4 + CHECKBOXSPACING * 2 + MAJORBORDER + MINORBORDER;
  2210.  
  2211.     radioGroup = NewRadioButtonGroup("Color Shading Radio");
  2212.  
  2213.     SetVar(radioGroup, HELPSTRING,
  2214.     NewString("These radio buttons allow you to change the way a visualization \
  2215. object is shaded with color.  This interacts in interesting ways with the light shading.  \
  2216. Experiment with different combinations."));
  2217.  
  2218.     /*Title box around it*/
  2219.     titleBox = NewTitleBox(left - MINORBORDER, right + MINORBORDER,
  2220.         top - 2 * CHECKBOXHEIGHT - CHECKBOXSPACING - MINORBORDER,
  2221.         top + CHECKBOXSPACING + TITLEBOXTOP + MINORBORDER,
  2222.         "Color Shading");
  2223.     PrefixList(panelContents, titleBox);
  2224.     SetVar(titleBox, PARENT, panelContents);
  2225.  
  2226.     checkBox = NewRadioButton(left, right, top - CHECKBOXHEIGHT, top,
  2227.         "Flat");
  2228.     SetVar(checkBox, HELPSTRING,
  2229.     NewString("This button specifies that the visualization object will \
  2230. be flatly shaded with color.  This only has a visual effect when the object \
  2231. is color shaded by another field.  It may be faster than smooth shading on \
  2232. some systems.  The combination of flat light and flat color shading may be even faster."));
  2233.     AddRadioButton(radioGroup, checkBox);
  2234.     top -= CHECKBOXHEIGHT + CHECKBOXSPACING;
  2235.  
  2236.     checkBox = NewRadioButton(left, right, top - CHECKBOXHEIGHT, top,
  2237.         "Smooth");
  2238.     SetVar(checkBox, HELPSTRING,
  2239.     NewString("This button specifies that the visualization object will \
  2240. be smoothly shaded with color.  This only has a visual effect when the object \
  2241. is color shaded with another field.  It may be slower than flat shading on \
  2242. some systems."));
  2243.     AddRadioButton(radioGroup, checkBox);
  2244.     top -= CHECKBOXHEIGHT + CHECKBOXSPACING;
  2245.  
  2246.     /*Add the radio button group*/
  2247.     PrefixList(panelContents, radioGroup);
  2248.     SetVar(radioGroup, PARENT, panelContents);
  2249.  
  2250.     /*Set its value based on color shading*/
  2251.     SetValue(radioGroup, NewInt(GetPredicate(object, COLORSHADING) ? 1 : 0));
  2252.  
  2253.     /*Associate it with the variable*/
  2254.     AssocDirectControlWithVar(radioGroup, object, COLORSHADING);
  2255.  
  2256.     return ObjTrue;
  2257. }
  2258.  
  2259. static ObjPtr AddDeformedControls(object, panelContents)
  2260. ObjPtr object, panelContents;
  2261. /*Adds controls appropriate to a deformed object to panelContents*/
  2262. {
  2263.     ObjPtr control, button, checkBox, corral, sw, textBox, slider, icon, radioGroup;
  2264.     ObjPtr deformObj, titleBox;
  2265.     ObjPtr var;
  2266.     int width, left, right, top, bottom, cellHeight, m1, m2;
  2267.     real baseColor[3];
  2268.     real hs[2], dummy;
  2269.     ObjPtr parent;
  2270.  
  2271.     /*Get the parent*/
  2272.     parent = GetObjectVar("AddDeformedControls", panelContents, PARENT);
  2273.  
  2274.     width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
  2275.     left = MAJORBORDER;
  2276.  
  2277.     cellHeight = ONECORRALHEIGHT;
  2278.  
  2279.     /*Precalculate the midlines for convenience*/
  2280.     m1 = CWINHEIGHT - MAJORBORDER - cellHeight / 2;
  2281.     m1 += MINORBORDER;
  2282.     m2 = m1 - cellHeight - MAJORBORDER - TEXTBOXHEIGHT - TEXTBOXSEP;
  2283.  
  2284.     /*Create the deform source corral*/
  2285.     corral = NewIconCorral(NULLOBJ,
  2286.                left, left + ONECORRALWIDTH,
  2287.                m2 - ONECORRALHEIGHT / 2,
  2288.                m2 + ONECORRALHEIGHT / 2, 0);
  2289.     SetVar(corral, SINGLECORRAL, ObjTrue);
  2290.     SetVar(corral, TOPDOWN, ObjTrue);
  2291.     SetVar(corral, NAME, NewString("Deform Field"));
  2292.     PrefixList(panelContents, corral);
  2293.     SetVar(corral, HELPSTRING,
  2294.     NewString("This corral shows the dataset that is used to \
  2295. deform the visualization object.  \
  2296. To replace it with another dataset, drag the icon of the other \
  2297. dataset into this corral."));
  2298.     SetVar(corral, PARENT, panelContents);
  2299.     SetVar(corral, REPOBJ, object);
  2300.     SetMethod(corral, DROPINCONTENTS, DropInDeformCorral);
  2301.  
  2302.     /*Create the deform source text box*/
  2303.     textBox = NewTextBox(left, left + ONECORRALWIDTH, 
  2304.              m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP - TEXTBOXHEIGHT,
  2305.              m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP,
  2306.              0, "Deform Field Text", "Deform Field");
  2307.     PrefixList(panelContents, textBox);
  2308.     SetVar(textBox, PARENT, panelContents);
  2309.     SetTextAlign(textBox, CENTERALIGN);
  2310.  
  2311.     left += ONECORRALWIDTH + MINORBORDER;
  2312.     deformObj = GetVar(object, DEFORMOBJ);
  2313.     if (deformObj)
  2314.     {
  2315.     ObjPtr name, defaultIcon;
  2316.     /*Drop icon in corral, if need be*/
  2317.     name = GetVar(deformObj, NAME);
  2318.     defaultIcon = GetVar(deformObj, DEFAULTICON);
  2319.     if (defaultIcon)
  2320.     {
  2321.         icon = NewObject(defaultIcon, 0);
  2322.         SetVar(icon, NAME, name);
  2323.     }
  2324.     else
  2325.     {
  2326.         icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
  2327.         }
  2328.     SetVar(icon, REPOBJ, deformObj);
  2329.     SetVar(icon, ICONLOC, NULLOBJ);
  2330.         DropIconInCorral(corral, icon);
  2331.     }
  2332.  
  2333.     /*Create the constant deformation control*/
  2334.     var = GetRealVar("AddDeformedControls", object, DEFCONSTANT);
  2335.     if (!var)
  2336.     {
  2337.     SetVar(object, DEFCONSTANT, NewReal(0.0));
  2338.     }
  2339.     textBox = NewTextBox(MAJORBORDER, left - MINORBORDER, 
  2340.             m1 - EDITBOXHEIGHT / 2,
  2341.             m1 + EDITBOXHEIGHT / 2, 
  2342.             EDITABLE + WITH_PIT + ONE_LINE,
  2343.             "Fixed Deformation", "");
  2344.     PrefixList(panelContents, textBox);
  2345.     SetVar(textBox, PARENT, panelContents);
  2346.     AssocTextRealControlWithVar(textBox, object, DEFCONSTANT, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  2347.     SetVar(textBox, HELPSTRING, NewString("This text box gives a constant \
  2348. deformation when it is selected by the switch."));
  2349.     SetVar(textBox, WHICHVAR, NewSymbol(DEFCONSTANT));
  2350.     SetTextAlign(textBox, RIGHTALIGN);
  2351.  
  2352.     /*Create the text box*/
  2353.     textBox = NewTextBox(MAJORBORDER - 20, left - MINORBORDER + 20, 
  2354.              m1 - EDITBOXHEIGHT / 2 - TEXTBOXSEP - 2 * TEXTBOXHEIGHT,
  2355.              m1 - EDITBOXHEIGHT / 2 - TEXTBOXSEP,
  2356.              0, "Fixed Deformation Text", "Fixed\nDeformation");
  2357.     PrefixList(panelContents, textBox);
  2358.     SetVar(textBox, PARENT, panelContents);
  2359.     SetTextAlign(textBox, CENTERALIGN);
  2360.     SetVar(textBox, REPOBJ, object);
  2361.  
  2362.     /*Create the choice switch*/
  2363.     var = GetIntVar("AddDeformedControls", object, DEFORMSWITCH);
  2364.     sw = NewSwitch(left, left + SWITCHWIDTH,
  2365.             m2 - cellHeight / 2 - (MAJORBORDER + TEXTBOXHEIGHT + TEXTBOXSEP) / 2,
  2366.             m1 + cellHeight / 2 + (MAJORBORDER + TEXTBOXHEIGHT + TEXTBOXSEP) / 2,
  2367.             2, 0, var ? GetInt(var) : 0,
  2368.             "Deform Switch");
  2369.     PrefixList(panelContents, sw);
  2370.     SetVar(sw, PARENT, panelContents);
  2371.     SetVar(sw, REPOBJ, object);
  2372.     SetVar(sw, HELPSTRING, NewString("This switch controls whether the \
  2373. deformation of the visualization object comes from a \
  2374. field or from a fixed deformation."));
  2375.  
  2376.     if (!var)
  2377.     {
  2378.     SetVar(object, DEFORMSWITCH, NewInt(0));
  2379.     }
  2380.     AssocDirectControlWithVar(sw, object, DEFORMSWITCH);
  2381.  
  2382.     left += SWITCHWIDTH + MINORBORDER;
  2383.  
  2384.     /*Create the * text box*/
  2385.     right = left + MINORBORDER;
  2386.     textBox = TemplateTextBox(VisDeformTemplate, "Splat", 0, "*");
  2387.     PrefixList(panelContents, textBox);
  2388.     SetVar(textBox, PARENT, panelContents);
  2389.     SetTextFont(textBox, "Courier-Bold");
  2390.     SetTextSize(textBox, 18);
  2391.     left = right + MINORBORDER;
  2392.  
  2393.     /*Create the deformation factor*/
  2394.     var = GetRealVar("AddDeformedControls", object, DEFFACTOR);
  2395.     if (!var)
  2396.     {
  2397.     SetVar(object, DEFFACTOR, NewReal(0.0));
  2398.     }
  2399.     right = left + DEFORMEDITWIDTH;
  2400.     textBox = TemplateTextBox(VisDeformTemplate, "Deformation Factor", 
  2401.             EDITABLE + WITH_PIT + ONE_LINE,
  2402.             "");
  2403.     PrefixList(panelContents, textBox);
  2404.     SetVar(textBox, PARENT, panelContents);
  2405.     AssocTextRealControlWithVar(textBox, object, DEFFACTOR, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  2406.     SetVar(textBox, HELPSTRING, NewString("This text box gives a multiplier \
  2407. for the deformation provided by the switch."));
  2408.     SetTextAlign(textBox, RIGHTALIGN);
  2409.  
  2410.     /*Create the text box*/
  2411.     textBox = TemplateTextBox(VisDeformTemplate, "Factor Text",
  2412.             0, "Factor");
  2413.     PrefixList(panelContents, textBox);
  2414.     SetVar(textBox, PARENT, panelContents);
  2415.     SetTextAlign(textBox, CENTERALIGN);
  2416.     SetVar(textBox, REPOBJ, object);
  2417.     left = right + MINORBORDER;
  2418.  
  2419.     /*Create the + text box*/
  2420.     right = left + MINORBORDER;
  2421.     textBox = TemplateTextBox(VisDeformTemplate, "Plus", 0, "+");
  2422.     PrefixList(panelContents, textBox);
  2423.     SetVar(textBox, PARENT, panelContents);
  2424.     SetTextFont(textBox, "Courier-Bold");
  2425.     SetTextSize(textBox, 18);
  2426.     left = right + MINORBORDER;
  2427.  
  2428.     /*Create the deformation offset*/
  2429.     var = GetRealVar("AddDeformedControls", object, DEFOFFSET);
  2430.     if (!var)
  2431.     {
  2432.     SetVar(object, DEFOFFSET, NewReal(0.0));
  2433.     }
  2434.     right = left + DEFORMEDITWIDTH;
  2435.     textBox = TemplateTextBox(VisDeformTemplate, "Deformation Offset", 
  2436.             EDITABLE + WITH_PIT + ONE_LINE, tempStr);
  2437.     PrefixList(panelContents, textBox);
  2438.     SetVar(textBox, PARENT, panelContents);
  2439.     AssocTextRealControlWithVar(textBox, object, DEFOFFSET, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  2440.     SetVar(textBox, HELPSTRING, NewString("This text box gives an offset \
  2441. for the deformation provided by the switch, multiplied by the multiplier."));
  2442.     SetVar(textBox, WHICHVAR, NewSymbol(DEFOFFSET));
  2443.     SetTextAlign(textBox, RIGHTALIGN);
  2444.  
  2445.     /*Create the text box*/
  2446.     textBox = TemplateTextBox(VisDeformTemplate, "Offset Text", 0, "Offset");
  2447.     PrefixList(panelContents, textBox);
  2448.     SetVar(textBox, PARENT, panelContents);
  2449.     SetTextAlign(textBox, CENTERALIGN);
  2450.     SetVar(textBox, REPOBJ, object);
  2451.     left = right + MINORBORDER;
  2452.  
  2453.     /*Create the Invert Surface check box*/
  2454.     left = MAJORBORDER;
  2455.     bottom = MAJORBORDER;
  2456.     top = bottom + CHECKBOXHEIGHT;
  2457.     button = NewCheckBox(left, right, bottom, top, "Invert Surface",
  2458.     GetPredicate(object, REVERSESENSE));
  2459.     PrefixList(panelContents, button);
  2460.     SetVar(button, PARENT, panelContents);
  2461.     AssocDirectControlWithVar(button, object, REVERSESENSE);
  2462.  
  2463.     return ObjTrue;
  2464. }
  2465.  
  2466. static ObjPtr AddSurfaceControls(object, panelContents)
  2467. ObjPtr object, panelContents;
  2468. /*Adds controls appropriate to a surface object to panelContents*/
  2469. {
  2470.     ObjPtr textBox, name, repObj, control, icon, checkBox, radioGroup, titleBox;
  2471.     ObjPtr var;
  2472.     ObjPtr panel;
  2473.     int width;
  2474.     real initValue;
  2475.     real shininess, specularity;
  2476.     int left, top, right, bottom, mid;
  2477.     ObjPtr contents;
  2478.     ObjPtr parent;
  2479.     ObjPtr scale;
  2480.  
  2481.     /*Get the parent*/
  2482.     parent = GetObjectVar("AddColoredControls", panelContents, PARENT);
  2483.  
  2484.     width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
  2485.  
  2486.     var = GetVar(object, SHINVAL);
  2487.     if (var && IsReal(var))
  2488.     {
  2489.     shininess = initValue = GetReal(var);
  2490.     }
  2491.     else
  2492.     {
  2493.     shininess = initValue = 80.0;
  2494.     }
  2495.  
  2496.     var = GetVar(object, SPECVAL);
  2497.     if (var && IsReal(var))
  2498.     {
  2499.     specularity = initValue = GetReal(var);
  2500.     }
  2501.     else
  2502.     {
  2503.     specularity = initValue = 0.2;
  2504.     }
  2505.  
  2506.     /*Create the highlights control*/
  2507.     top = CWINHEIGHT - MINORBORDER;
  2508.     left = MINORBORDER;
  2509.     bottom = MINORBORDER;
  2510.     control = NewXYControl(left + ICONSIZE / 2 + ICONXYSEP, 
  2511.                left + ICONSIZE / 2 + ICONXYSEP + XYCONTROLWIDTH,
  2512.                top - ICONSIZE / 2 - ICONXYSEP - XYCONTROLWIDTH,
  2513.                top - ICONSIZE / 2 - ICONXYSEP,"Highlights");
  2514.     if (!control) return ObjFalse;
  2515.     PrefixList(panelContents, control);
  2516.     SetVar(control, PARENT, panelContents);
  2517.     SetXYControlLimits(control, 5.0, 128.0, 0.0, 1.0);
  2518.     SetXYControlValue(control, shininess, specularity);
  2519.     SetMethod(control, CHANGEDVALUE, ChangeReflection);
  2520.     DeclareIndirectDependency(control, APPEARANCE, REPOBJ, SHINVAL);
  2521.     DeclareIndirectDependency(control, APPEARANCE, REPOBJ, SPECVAL);
  2522.     SetMethod(control, APPEARANCE, MakeReflectionAppearance);
  2523.     SetVar(control, HELPSTRING, NewString("This control changes the specular highlights \
  2524. of a visualization object.  Move the indicator up to make the highlights brighter and down \
  2525. to make them dimmer.  Move it right to make the highlights sharper and left \
  2526. to make them dimmer.  The icons at the four corners of the control give a rough \
  2527. idea of the effect.  The effect on real visualization objects, however, is often quite \
  2528. subtle."));
  2529.     SetVar(control, REPOBJ, object);
  2530.  
  2531.     /*Create associated icons*/
  2532.     icon = NewIcon(left + ICONSIZE / 2,
  2533.            top - XYCONTROLWIDTH - ICONSIZE / 2 - 2 * ICONXYSEP + ICONSHADOW,
  2534.            ICONDIMDIF, (char *) 0);
  2535.     if (!icon) return ObjFalse;
  2536.     PrefixList(panelContents, icon);
  2537.     SetVar(icon, PARENT, panelContents);
  2538.     SetMethod(icon, PRESS, (FuncTyp) 0);
  2539.  
  2540.     icon = NewIcon(left + ICONSIZE / 2,
  2541.            top - ICONSIZE / 2,
  2542.            ICONBRTDIF, (char *) 0);
  2543.     if (!icon) return ObjFalse;
  2544.     PrefixList(panelContents, icon);
  2545.     SetVar(icon, PARENT, panelContents);
  2546.     SetMethod(icon, PRESS, (FuncTyp) 0);
  2547.  
  2548.     icon = NewIcon(left + XYCONTROLWIDTH + ICONSIZE / 2 + 2 * ICONXYSEP,
  2549.            top - XYCONTROLWIDTH - ICONSIZE / 2 - 2 * ICONXYSEP + ICONSHADOW,
  2550.            ICONDIMTIGHT, (char *) 0);
  2551.     if (!icon) return ObjFalse;
  2552.     PrefixList(panelContents, icon);
  2553.     SetVar(icon, PARENT, panelContents);
  2554.     SetMethod(icon, PRESS, (FuncTyp) 0);
  2555.  
  2556.     icon = NewIcon(left + XYCONTROLWIDTH + ICONSIZE / 2 + 2 * ICONXYSEP,
  2557.            top - ICONSIZE / 2,
  2558.            ICONBRTTIGHT, (char *) 0);
  2559.     if (!icon) return ObjFalse;
  2560.     PrefixList(panelContents, icon);
  2561.     SetVar(icon, PARENT, panelContents);
  2562.     SetMethod(icon, PRESS, (FuncTyp) 0);
  2563.  
  2564.     /*Create the highlights text box*/
  2565.     textBox = NewTextBox(left, left + 2 * ICONXYSEP + XYCONTROLWIDTH + ICONSIZE, 
  2566.              top - XYCONTROLWIDTH - ICONSIZE - ICONXYSEP - TEXTBOXHEIGHT,
  2567.              top - XYCONTROLWIDTH - ICONSIZE - ICONXYSEP,
  2568.              0, "Highlights Text", "Highlights");
  2569.     if (!textBox) return ObjFalse;
  2570.     PrefixList(panelContents, textBox);
  2571.     SetVar(textBox, PARENT, panelContents);
  2572.     SetTextAlign(textBox, CENTERALIGN);
  2573.  
  2574.     mid = left + ICONXYSEP + (XYCONTROLWIDTH + ICONSIZE) / 2;
  2575.  
  2576.     /*Create the highlight color control*/
  2577.     control = NewColorWheel(mid - COLORWHEELWIDTH / 2, mid + COLORWHEELWIDTH / 2,
  2578.             bottom + TEXTBOXHEIGHT + TEXTBOXSEP, 
  2579.             bottom + TEXTBOXHEIGHT + TEXTBOXSEP + COLORWHEELWIDTH,
  2580.             "Highlight Color");
  2581.     PrefixList(panelContents, control);
  2582.     SetVar(control, PARENT, panelContents);
  2583.     SetVar(control, HELPSTRING, NewString("This color wheel controls the color of the specular highlights \
  2584. on a visualization object.  The effects are usually quite subtle and are most useful on objects with \
  2585. a fixed base color.")); 
  2586.  
  2587.     var = GetVar(object, HIGHLIGHTCOLOR);
  2588.     if (!var)
  2589.     {
  2590.     real *highlightColor;
  2591.  
  2592.     var = NewRealArray(1, 3L);
  2593.     highlightColor[0] = 1.0;
  2594.     highlightColor[1] = 1.0;
  2595.     highlightColor[2] = 1.0;
  2596.     SetVar(object, HIGHLIGHTCOLOR, var);
  2597.     }
  2598.     AssocColorControlWithVar(control, object, HIGHLIGHTCOLOR);
  2599.  
  2600.     /*Create the text box*/
  2601.     textBox = NewTextBox(left, 2 * mid - left, 
  2602.             bottom, 
  2603.             bottom + TEXTBOXHEIGHT,
  2604.              0, "Highlight Color Text", "Highlight Color");
  2605.     PrefixList(panelContents, textBox);
  2606.     SetVar(textBox, PARENT, panelContents);
  2607.     SetTextAlign(textBox, CENTERALIGN);
  2608.  
  2609.     left = width - MAJORBORDER - TRANSPARENTWIDTH;
  2610.  
  2611.     bottom = MAJORBORDER;
  2612.  
  2613.     /*Create the transparent check box, or use the existing one*/
  2614.     if (checkBox = GetVar(parent, TRANSPARENTCNT))
  2615.     {
  2616.     PrefixList(panelContents, checkBox);
  2617.     }
  2618.     else
  2619.     {
  2620.     checkBox = NewCheckBox(left, width, 
  2621.         bottom,
  2622.         bottom + CHECKBOXHEIGHT, "Transparent", GetPredicate(object, ISTRANSPARENT));
  2623.     if (!checkBox)
  2624.     {
  2625.         return ObjFalse;
  2626.     }
  2627.     PrefixList(panelContents, checkBox);
  2628.     SetVar(checkBox, HELPSTRING,
  2629.         NewString("If this box is checked, the visualization object will be drawn using alpha transparency.  \
  2630. It may be useful to turn down the brightness of the object when using this feature.  Transparency \
  2631. only works on hardware that supports blending transparency.  If you don't \
  2632. have this hardware, try translucency instead."));
  2633.     SetVar(checkBox, PARENT, parent);
  2634.     if (!GetVar(object, ISTRANSPARENT))
  2635.     {
  2636.         SetVar(object, ISTRANSPARENT, ObjFalse);
  2637.     }
  2638.     AssocDirectControlWithVar(checkBox, object, ISTRANSPARENT);
  2639.     SetVar(parent, TRANSPARENTCNT, checkBox);
  2640.  
  2641. #ifdef GRAPHICS
  2642.     if (!hasTransparency) ActivateButton(checkBox, false);
  2643. #endif
  2644.     }
  2645.  
  2646.     bottom += CHECKBOXHEIGHT + MINORBORDER;
  2647.  
  2648.     /*Create the translucent check box, or use the existing one*/
  2649.     if (checkBox = GetVar(parent, TRANSLUCENTCNT))
  2650.     {
  2651.     PrefixList(panelContents, checkBox);
  2652.     }
  2653.     else
  2654.     {
  2655.     checkBox = NewCheckBox(left, width, 
  2656.         bottom,
  2657.         bottom + CHECKBOXHEIGHT, "Translucent", GetPredicate(object, ISTRANSLUCENT));
  2658.     if (!checkBox)
  2659.     {
  2660.         return ObjFalse;
  2661.     }
  2662.     PrefixList(panelContents, checkBox);
  2663.     SetVar(checkBox, HELPSTRING,
  2664.         NewString("If this box is checked, the visualization object will be drawn using screen door translucency."));
  2665.     SetVar(checkBox, PARENT, parent);
  2666.     if (!GetVar(object, ISTRANSLUCENT))
  2667.     {
  2668.         SetVar(object, ISTRANSLUCENT, ObjFalse);
  2669.     }
  2670.     AssocDirectControlWithVar(checkBox, object, ISTRANSLUCENT);
  2671.     SetVar(parent, TRANSLUCENTCNT, checkBox);
  2672.     }
  2673.  
  2674.     bottom += CHECKBOXHEIGHT + MINORBORDER;
  2675.  
  2676.     /*Create the two-sided check box*/
  2677.     checkBox = NewCheckBox(left, width, 
  2678.         bottom,
  2679.         bottom + CHECKBOXHEIGHT, "2-Sided Lighting", GetPredicate(object, TWOSIDEDSURFACE));
  2680.     if (!checkBox)
  2681.     {
  2682.     return ObjFalse;
  2683.     }
  2684.     PrefixList(panelContents, checkBox);
  2685.     SetVar(checkBox, HELPSTRING,
  2686.     NewString("If this box is checked, the visualization object will be drawn \
  2687. with lighting on both sided of the surface."));
  2688.     SetVar(checkBox, PARENT, parent);
  2689.     if (!GetVar(object, TWOSIDEDSURFACE)) SetVar(object, TWOSIDEDSURFACE, NewInt(0));
  2690.     AssocDirectControlWithVar(checkBox, object, TWOSIDEDSURFACE);
  2691.  
  2692.     bottom += CHECKBOXHEIGHT + MINORBORDER;
  2693.  
  2694.     /*Create radio button group for light shading*/
  2695.     right = width - MAJORBORDER;
  2696.     top = bottom + CHECKBOXHEIGHT * 3 + CHECKBOXSPACING + MINORBORDER;
  2697.  
  2698.     radioGroup = NewRadioButtonGroup("Light Shading Radio");
  2699.  
  2700.     SetVar(radioGroup, HELPSTRING,
  2701.     NewString("These radio buttons allow you to change the way a visualization \
  2702. object is shaded with the light sources.  Light shading will only work in windows set to \
  2703. full color mode.  This control interacts in interesting ways with the color shading.  \
  2704. Experiment with different combinations."));
  2705.     /*Title box around it*/
  2706.     titleBox = NewTitleBox(left - MINORBORDER, right + MINORBORDER,
  2707.         bottom,
  2708.         top + TITLEBOXTOP + MINORBORDER,
  2709.         "Light Shading");
  2710.     PrefixList(panelContents, titleBox);
  2711.     SetVar(titleBox, PARENT, panelContents);
  2712.  
  2713.     checkBox = NewRadioButton(left, right, top - CHECKBOXHEIGHT, top,
  2714.         "None");
  2715.     SetVar(checkBox, HELPSTRING,
  2716.     NewString("This button specifies that the visualization object will \
  2717. not be shaded with light at all.  This will produce a silhouette effect when the \
  2718. color is fixed and will produce an intensely colored surface with no \
  2719. lighting cues when the color is from a field."));
  2720.     AddRadioButton(radioGroup, checkBox);
  2721.     top -= CHECKBOXHEIGHT + CHECKBOXSPACING;
  2722.  
  2723.     checkBox = NewRadioButton(left, right, top - CHECKBOXHEIGHT, top,
  2724.         "Flat");
  2725.     SetVar(checkBox, HELPSTRING,
  2726.     NewString("This button specifies that the visualization object will \
  2727. be flatly shaded with light.  This may be faster on some systems than smooth light \
  2728. shading.  The combination of flat light and flat color shading may be even faster."));
  2729.     AddRadioButton(radioGroup, checkBox);
  2730.     top -= CHECKBOXHEIGHT + CHECKBOXSPACING;
  2731.  
  2732.     checkBox = NewRadioButton(left, right, top - CHECKBOXHEIGHT, top,
  2733.         "Smooth");
  2734.     SetVar(checkBox, HELPSTRING,
  2735.     NewString("This button specifies that the visualization object will \
  2736. be smoothly shaded with light.  This may be slower on some systems than flat light \
  2737. shading."));
  2738.     AddRadioButton(radioGroup, checkBox);
  2739.     top -= CHECKBOXHEIGHT + CHECKBOXSPACING;
  2740.  
  2741.     /*Add the radio button group*/
  2742.     PrefixList(panelContents, radioGroup);
  2743.     SetVar(radioGroup, PARENT, panelContents);
  2744.  
  2745.     /*Set its value based on color shading*/
  2746.     var = GetVar(object, LIGHTSHADING);
  2747.     if (!var)
  2748.     {
  2749.     SetVar(object, LIGHTSHADING, NewInt(0));
  2750.     }
  2751.  
  2752.     AssocDirectControlWithVar(radioGroup, object, LIGHTSHADING);
  2753.  
  2754.     /*Add checkboxes for draw surface and draw wire frame*/
  2755.     top = CWINHEIGHT - MAJORBORDER;
  2756.     right = width - MAJORBORDER;
  2757.     left = right - SCDRAWBOXLENGTH;
  2758.  
  2759.     checkBox = NewCheckBox(left, right, top - CHECKBOXHEIGHT, top,
  2760.         "Draw Surface", GetPredicate(object, DRAWSURFACE));
  2761.     SetVar(checkBox, PARENT, panelContents);
  2762.     PrefixList(panelContents, checkBox);
  2763.     SetVar(checkBox, HELPSTRING,
  2764.     NewString("When this box is checked, the surface of the visualization will \
  2765. be drawn.  When it is not checked, the surface will not be drawn."));
  2766.     if (!GetVar(object, DRAWSURFACE)) SetVar(object, DRAWSURFACE, NewInt(0));
  2767.     AssocDirectControlWithVar(checkBox, object, DRAWSURFACE);
  2768.     top -= CHECKBOXHEIGHT + CHECKBOXSPACING;
  2769.  
  2770. #ifdef GRAPHOBJ
  2771.     checkBox = NewCheckBox(left, right, top - CHECKBOXHEIGHT, top,
  2772.         "Cache Graphics", GetPredicate(object, CACHEGRAPHICS));
  2773.     SetVar(checkBox, PARENT, panelContents);
  2774.     PrefixList(panelContents, checkBox);
  2775.     SetVar(checkBox, HELPSTRING,
  2776.     NewString("When this box is checked, the graphics of the visualization \
  2777. object will be cached in a graphical object.  This will speed up drawing during interaction \
  2778. but will use a lot of memory."));
  2779.     if (!GetVar(object, CACHEGRAPHICS)) SetVar(object, CACHEGRAPHICS, NewInt(0));
  2780.     AssocDirectControlWithVar(checkBox, object, CACHEGRAPHICS);
  2781.     top -= CHECKBOXHEIGHT + CHECKBOXSPACING;
  2782. #endif
  2783.  
  2784.     return ObjTrue;
  2785. }
  2786.  
  2787. static ObjPtr AddLineControls(object, panelContents)
  2788. ObjPtr object, panelContents;
  2789. /*Adds controls appropriate to a line object to panelContents*/
  2790. {
  2791.     ObjPtr checkBox, textBox, slider, scale;
  2792.     ObjPtr var;
  2793.  
  2794.     /*Add checkbox for draw wire frame*/
  2795.     checkBox = TemplateCheckBox(VisWireFrameTemplate, 
  2796.     "Draw Lines", GetPredicate(object, DRAWWIREFRAME));
  2797.     SetVar(checkBox, PARENT, panelContents);
  2798.     PrefixList(panelContents, checkBox);
  2799.     SetVar(checkBox, HELPSTRING,
  2800.     NewString("When this box is checked, a wire frame representation of the visualization will \
  2801. be drawn.  When it is not checked, the wire frame will not be drawn."));
  2802.     if (!GetVar(object, DRAWWIREFRAME)) SetVar(object, DRAWWIREFRAME, NewInt(0));
  2803.     AssocDirectControlWithVar(checkBox, object, DRAWWIREFRAME);
  2804.  
  2805.     checkBox = TemplateCheckBox(VisWireFrameTemplate, "Depth Cueing", GetPredicate(object, DEPTHCUELINES));
  2806.     SetVar(checkBox, PARENT, panelContents);
  2807.     PrefixList(panelContents, checkBox);
  2808.     SetVar(checkBox, HELPSTRING,
  2809.     NewString("When this box is checked, the wire frame will be drawn with depth \
  2810. cueing, which makes closer parts of the object appear brighter.  You may need to \
  2811. adjust the near and far clipping planes in the Observer controls to bring out the full \
  2812. range of brightness.  When it is not checked, the wire frame will be drawn without depth cueing."));
  2813.     if (!GetVar(object, DEPTHCUELINES)) SetVar(object, DEPTHCUELINES, NewInt(0));
  2814.     AssocDirectControlWithVar(checkBox, object, DEPTHCUELINES);
  2815.     if (!hasDepthCue)
  2816.     {
  2817.     ActivateButton(checkBox, false);
  2818.     }
  2819.  
  2820.     checkBox = TemplateCheckBox(VisWireFrameTemplate, "Antialiasing", GetPredicate(object, ANTIALIASLINES));
  2821.     SetVar(checkBox, PARENT, panelContents);
  2822.     PrefixList(panelContents, checkBox);
  2823.     SetVar(checkBox, HELPSTRING,
  2824.     NewString("When this box is checked, the wire frame will be drawn antialiased.  \
  2825. This will make the lines appear smoother, while sacrificing some speed.  \
  2826. When it is not checked, the wire frame will be drawn without antialiasing.\n\
  2827. \n\
  2828. Antialiasing only works if your computer supports it and the renderer is in \
  2829. full color mode.  Some models of workstation cannot display antialised lines of \
  2830. width greater than one.  Antialiasing may interact with other objects in the scene.  \
  2831. In general, it is good in scenes where there are few or no surfaces.  Experiment \
  2832. to find out if antialiasing is good for your data."));
  2833.     if (!GetVar(object, ANTIALIASLINES)) SetVar(object, ANTIALIASLINES, NewInt(0));
  2834.     AssocDirectControlWithVar(checkBox, object, ANTIALIASLINES);
  2835.     if (!hasAntialiasedLines)
  2836.     {
  2837.     ActivateButton(checkBox, false);
  2838.     }
  2839.  
  2840.     scale = TemplateScale(VisWireFrameTemplate, "Width Scale", SO_TOP, false);
  2841.     SetScaleStepPixels(scale, 10);
  2842.     PrefixList(panelContents, scale);
  2843.     SetVar(scale, PARENT, panelContents);
  2844.  
  2845.     /*Make the line width slider*/
  2846.     slider = TemplateSlider(VisWireFrameTemplate, "Width Slider", SCALE);
  2847.     PrefixList(panelContents, slider);
  2848.     SetVar(slider, PARENT, panelContents);
  2849.     LinkScale(scale, slider);
  2850.     var = GetVar(object, LINEWIDTH);
  2851.     SetSliderRange(slider, 10.0, 1.0, 1.0);
  2852.     SetSliderScale(slider, 2.0, 1.0, 0.0, "%g");
  2853.     AssocDirectControlWithVar(slider, object, LINEWIDTH);
  2854.     if (!var) SetVar(object, LINEWIDTH, NewReal(1.0));
  2855.     SetVar(slider, HELPSTRING, NewString("This slider controls the width of \
  2856. the wire frame of the visualization object in screen pixels."));
  2857.  
  2858.     /*Make a legend*/
  2859.     textBox = TemplateTextBox(VisWireFrameTemplate, "Line Width Legend", 0, "Line Width");
  2860.     SetVar(textBox, PARENT, panelContents);
  2861.     PrefixList(panelContents, textBox);
  2862.     SetTextAlign(textBox, RIGHTALIGN);    
  2863.     SetVar(textBox, HELPSTRING, NewString("This text boxc controls the width of \
  2864. the wire frame of the visualization object in screen pixels."));
  2865.  
  2866.     /*Make a slider readout*/
  2867.     textBox = TemplateTextBox(VisWireFrameTemplate, "Width Slider Readout", EDITABLE + WITH_PIT + ONE_LINE, "");
  2868.     SetVar(textBox, REPOBJ, object);
  2869.     SetVar(textBox, PARENT, panelContents);
  2870.     PrefixList(panelContents, textBox);
  2871.     SetTextAlign(textBox, RIGHTALIGN);
  2872.     SliderReadout(slider, textBox);
  2873.  
  2874.     /*And "pixels"*/
  2875.     textBox = TemplateTextBox(VisWireFrameTemplate, "Pixels Legend", 0, "Pixels");
  2876.     SetVar(textBox, PARENT, panelContents);
  2877.     PrefixList(panelContents, textBox);
  2878.  
  2879.     return ObjTrue;
  2880. }
  2881.  
  2882. static ObjPtr AddDotsControls(object, panelContents)
  2883. ObjPtr object, panelContents;
  2884. /*Adds controls appropriate to a dots object to panelContents*/
  2885. {
  2886.     ObjPtr checkBox, textBox, slider;
  2887.     ObjPtr var;
  2888.  
  2889.     /*Add checkbox for draw wire frame*/
  2890.     checkBox = TemplateCheckBox(VisDotsTemplate, 
  2891.     "Draw Dots", GetPredicate(object, DRAWDOTS));
  2892.     SetVar(checkBox, PARENT, panelContents);
  2893.     PrefixList(panelContents, checkBox);
  2894.     SetVar(checkBox, HELPSTRING,
  2895.     NewString("When this box is checked, a dots representation of the visualization will \
  2896. be drawn.  When it is not checked, the dots will not be drawn."));
  2897.     if (!GetVar(object, DRAWDOTS)) SetVar(object, DRAWDOTS, NewInt(0));
  2898.     AssocDirectControlWithVar(checkBox, object, DRAWDOTS);
  2899.  
  2900.     checkBox = TemplateCheckBox(VisDotsTemplate, "Depth Cueing", GetPredicate(object, DEPTHCUEDOTS));
  2901.     SetVar(checkBox, PARENT, panelContents);
  2902.     PrefixList(panelContents, checkBox);
  2903.     SetVar(checkBox, HELPSTRING,
  2904.     NewString("When this box is checked, the dots will be drawn with depth \
  2905. cueing, which makes closer parts of the object appear brighter.  You may need to \
  2906. adjust the near and far clipping planes in the Observer controls to bring out the full \
  2907. range of brightness.  When it is not checked, the dots will be drawn without depth cueing."));
  2908.     if (!GetVar(object, DEPTHCUEDOTS)) SetVar(object, DEPTHCUEDOTS, NewInt(0));
  2909.     AssocDirectControlWithVar(checkBox, object, DEPTHCUEDOTS);
  2910.     if (!hasDepthCue)
  2911.     {
  2912.     ActivateButton(checkBox, false);
  2913.     }
  2914.  
  2915.     checkBox = TemplateCheckBox(VisDotsTemplate, "Antialiasing", GetPredicate(object, ANTIALIASDOTS));
  2916.     SetVar(checkBox, PARENT, panelContents);
  2917.     PrefixList(panelContents, checkBox);
  2918.     SetVar(checkBox, HELPSTRING,
  2919.     NewString("When this box is checked, the dots will be drawn antialiased.  \
  2920. This will make the dots appear smoother, while sacrificing some speed.  \
  2921. When it is not checked, the dots will be drawn without antialiasing.\n\
  2922. \n\
  2923. Antialiasing only works if your computer supports it and the renderer is in \
  2924. full color mode.  Some models of workstation cannot display antialised dots of \
  2925. soze greater than one.  Antialiasing may interact with other objects in the scene.  \
  2926. In general, it is good in scenes where there are few or no surfaces.  Experiment \
  2927. to find out if antialiasing is good for your data."));
  2928.     if (!GetVar(object, ANTIALIASDOTS)) SetVar(object, ANTIALIASDOTS, NewInt(0));
  2929.     AssocDirectControlWithVar(checkBox, object, ANTIALIASDOTS);
  2930.     if (!hasAntialiasedPoints)
  2931.     {
  2932.     ActivateButton(checkBox, false);
  2933.     }
  2934.  
  2935.     checkBox = TemplateCheckBox(VisDotsTemplate, "Bigger Dots", GetPredicate(object, BIGGERDOTS));
  2936.     SetVar(checkBox, PARENT, panelContents);
  2937.     PrefixList(panelContents, checkBox);
  2938.     SetVar(checkBox, HELPSTRING,
  2939.     NewString("When this box is checked, the dots will be drawn a little larger.  \
  2940. On some systems, bigger dots cannot be antialiased"));
  2941.     if (!GetVar(object, BIGGERDOTS)) SetVar(object, BIGGERDOTS, NewInt(0));
  2942.     AssocDirectControlWithVar(checkBox, object, BIGGERDOTS);
  2943.  
  2944.     return ObjTrue;
  2945. }
  2946.  
  2947. Bool GetBounds(object, bounds)
  2948. ObjPtr object;
  2949. real bounds[6];
  2950. /*Gets the bounds of an object*/
  2951. {
  2952.     int k;
  2953.     real *meat;
  2954.     real temp;
  2955.     ObjPtr boundsArray;
  2956.  
  2957.     MakeVar(object, BOUNDS);
  2958.     boundsArray = GetVar(object, BOUNDS);
  2959.     if (boundsArray)
  2960.     {
  2961.     meat = ELEMENTS(boundsArray);
  2962.     for (k = 0; k < 6; ++k)
  2963.     {
  2964.         bounds[k] = meat[k];
  2965.     }
  2966.     if (bounds[0] > bounds[1])
  2967.     {
  2968.         temp = bounds[0];
  2969.         bounds[0] = bounds[1];
  2970.         bounds[1] = temp;
  2971.     }
  2972.     if (bounds[2] > bounds[3])
  2973.     {
  2974.         temp = bounds[2];
  2975.         bounds[2] = bounds[3];
  2976.         bounds[3] = temp;
  2977.     }
  2978.     if (bounds[4] > bounds[5])
  2979.     {
  2980.         temp = bounds[4];
  2981.         bounds[4] = bounds[5];
  2982.         bounds[5] = temp;
  2983.     }
  2984.     return true;
  2985.     }
  2986.     else
  2987.     {
  2988.     return false;
  2989.     }
  2990. }
  2991.  
  2992. static Bool GetTicParams(object, lowTic, nTics, ticSpace, initMinor, majorEvery) 
  2993. ObjPtr object;
  2994. real lowTic[3];
  2995. int nTics[3];
  2996. real ticSpace[3];
  2997. int initMinor[3];
  2998. int majorEvery[3];
  2999. /*Returns tic parameters for object object into 
  3000.   lowTic[d]    =    Value of lowest tic mark for dim d
  3001.   nTics[d]    =    Number of total tics for dim d
  3002.   ticSpace[d]    =    Spacing between tic marks
  3003.   initMinor[d]    =    Number of minor tics to start for dim d
  3004.   majorEvery[d] =    A major tic every majorEvery[d] + 1 tics
  3005. */
  3006. {
  3007.     ObjPtr formObj;
  3008.     real bounds[6];
  3009.     int k;
  3010.     ObjPtr repObj;
  3011.  
  3012.     /*Get the bounds*/
  3013.     if (!GetBounds(object, bounds))
  3014.     {
  3015.     return false;
  3016.     }
  3017.  
  3018.     repObj = GetVar(object, MAINDATASET);
  3019.     if (!repObj) repObj = GetObjectVar("GetTicParams", object, REPOBJ);
  3020.     if (!repObj)
  3021.     {
  3022.     return false;
  3023.     }
  3024.  
  3025.     /*See if the object has a data form*/
  3026.     formObj = GetVar(repObj, DATAFORM);
  3027.     if (formObj)
  3028.     {
  3029.     ObjPtr dimsArray;
  3030.     real dims[3];
  3031.     /*Make major tics go around grid points*/
  3032.  
  3033.     dimsArray = GetFixedArrayVar("GetTicParams", formObj, DIMENSIONS, 1, 3L);
  3034.     if (!dimsArray)
  3035.     {
  3036.         return false;
  3037.     }
  3038.     Array2CArray(dims, dimsArray);
  3039.  
  3040.     for (k = 0; k < 3; ++k)
  3041.     {
  3042.         lowTic[k] = bounds[k + k];
  3043.         nTics[k] = (int) (dims[k] + 4.0 * (dims[k] - 1));
  3044.         ticSpace[k] = (bounds[k + k + 1] - bounds[k + k]) / (dims[k] - 1.0) / 5;
  3045.         initMinor[k] = 0;
  3046.         majorEvery[k] = 4;
  3047.     }
  3048.     return true;
  3049.     }
  3050.     else
  3051.     {
  3052.     /*Guess tic marks*/
  3053.     return false;
  3054.     }
  3055. }
  3056.  
  3057. static ObjPtr DrawBounded(object)
  3058. ObjPtr object;
  3059. /*Draw stuff around a bounded object*/
  3060. {
  3061. #ifdef GRAPHICS
  3062.     ObjPtr flagsObj;
  3063.     int flags;
  3064.     real bounds[6], scaledBounds[6];
  3065.     real maxSize = 0;
  3066.     ObjPtr dataset;
  3067.     ObjPtr var;
  3068.     Bool drawEditBox;
  3069.  
  3070.     if (DQ_OUTLINE < minDrawingQuality || DQ_OUTLINE > maxDrawingQuality)
  3071.     {
  3072.     /*Not supposed to draw the outline*/
  3073.     return ObjFalse;
  3074.     }
  3075.  
  3076.     dataset = GetVar(object, MAINDATASET);
  3077.     if (!dataset) dataset = GetObjectVar("DrawBounded", object, REPOBJ);
  3078.     if (!dataset)
  3079.     {
  3080.     return ObjFalse;
  3081.     }
  3082.  
  3083.     flagsObj = GetVar(object, BBFLAGS);
  3084.     if (flagsObj)
  3085.     {
  3086.     flags = GetInt(flagsObj);
  3087.     }
  3088.     else
  3089.     {
  3090.     flags = 0;
  3091.     }
  3092.  
  3093.     if (GetBounds(object, bounds))
  3094.     {
  3095.     if (bounds[1] - bounds[0] > maxSize) maxSize = bounds[1] - bounds[0];
  3096.     if (bounds[3] - bounds[2] > maxSize) maxSize = bounds[3] - bounds[2];
  3097.     if (bounds[5] - bounds[4] > maxSize) maxSize = bounds[5] - bounds[4];
  3098.  
  3099.     scaledBounds[0] = bounds[0];
  3100.     scaledBounds[1] = bounds[1];
  3101.     scaledBounds[2] = bounds[2];
  3102.     scaledBounds[3] = bounds[3];
  3103.     scaledBounds[4] = bounds[4];
  3104.     scaledBounds[5] = bounds[5];
  3105.  
  3106.     /*See if we need to draw the edit box*/
  3107.     drawEditBox = false;
  3108. #if 0
  3109.     if (IsSelected(object))
  3110.     {
  3111.         var = GetVar(curSpace, EDITTOOL);
  3112.         if (var)
  3113.         {
  3114.         if (GetInt(var) == ST_3DFINGER)
  3115.         {
  3116.             drawEditBox = true;
  3117.         }
  3118.         }
  3119.     }
  3120. #endif
  3121.  
  3122.     if (drawEditBox)
  3123.     {
  3124.         SetLineWidth(2);
  3125.         SetUIColor(UIWHITE);
  3126.  
  3127.         /*Draw bottom square*/
  3128.         qualityDrawnSoFar = MAX(qualityDrawnSoFar, DQ_OUTLINE);
  3129.         DrawSpaceLine(scaledBounds[0], scaledBounds[2], scaledBounds[4], scaledBounds[1], scaledBounds[2], scaledBounds[4]);
  3130.         DrawSpaceLine(scaledBounds[1], scaledBounds[2], scaledBounds[4], scaledBounds[1], scaledBounds[3], scaledBounds[4]);
  3131.         DrawSpaceLine(scaledBounds[1], scaledBounds[3], scaledBounds[4], scaledBounds[0], scaledBounds[3], scaledBounds[4]);
  3132.         DrawSpaceLine(scaledBounds[0], scaledBounds[3], scaledBounds[4], scaledBounds[0], scaledBounds[2], scaledBounds[4]);
  3133.  
  3134.         /*Draw top square*/
  3135.         DrawSpaceLine(scaledBounds[0], scaledBounds[2], scaledBounds[5], scaledBounds[1], scaledBounds[2], scaledBounds[5]);
  3136.         DrawSpaceLine(scaledBounds[1], scaledBounds[2], scaledBounds[5], scaledBounds[1], scaledBounds[3], scaledBounds[5]);
  3137.         DrawSpaceLine(scaledBounds[1], scaledBounds[3], scaledBounds[5], scaledBounds[0], scaledBounds[3], scaledBounds[5]);
  3138.         DrawSpaceLine(scaledBounds[0], scaledBounds[3], scaledBounds[5], scaledBounds[0], scaledBounds[2], scaledBounds[5]);
  3139.  
  3140.         /*Draw remaining sides*/
  3141.         DrawSpaceLine(scaledBounds[0], scaledBounds[2], scaledBounds[4], scaledBounds[0], scaledBounds[2], scaledBounds[5]);
  3142.         DrawSpaceLine(scaledBounds[1], scaledBounds[2], scaledBounds[4], scaledBounds[1], scaledBounds[2], scaledBounds[5]);
  3143.         DrawSpaceLine(scaledBounds[1], scaledBounds[3], scaledBounds[4], scaledBounds[1], scaledBounds[3], scaledBounds[5]);
  3144.         DrawSpaceLine(scaledBounds[0], scaledBounds[3], scaledBounds[4], scaledBounds[0], scaledBounds[3], scaledBounds[5]);
  3145.  
  3146.         SetLineWidth(1);
  3147.     }
  3148.     else if (maxDrawingQuality == DQ_OUTLINE &&
  3149.          qualityDrawnSoFar <= DQ_MIN)
  3150.     {
  3151.         /*Do the outline anyway*/
  3152.         SetUIColor(UIRED);
  3153.  
  3154.         /*Draw bottom square*/
  3155.         qualityDrawnSoFar = MAX(qualityDrawnSoFar, DQ_OUTLINE);
  3156.         DrawSpaceLine(scaledBounds[0], scaledBounds[2], scaledBounds[4], scaledBounds[1], scaledBounds[2], scaledBounds[4]);
  3157.         DrawSpaceLine(scaledBounds[1], scaledBounds[2], scaledBounds[4], scaledBounds[1], scaledBounds[3], scaledBounds[4]);
  3158.         DrawSpaceLine(scaledBounds[1], scaledBounds[3], scaledBounds[4], scaledBounds[0], scaledBounds[3], scaledBounds[4]);
  3159.         DrawSpaceLine(scaledBounds[0], scaledBounds[3], scaledBounds[4], scaledBounds[0], scaledBounds[2], scaledBounds[4]);
  3160.  
  3161.         /*Draw top square*/
  3162.         DrawSpaceLine(scaledBounds[0], scaledBounds[2], scaledBounds[5], scaledBounds[1], scaledBounds[2], scaledBounds[5]);
  3163.         DrawSpaceLine(scaledBounds[1], scaledBounds[2], scaledBounds[5], scaledBounds[1], scaledBounds[3], scaledBounds[5]);
  3164.         DrawSpaceLine(scaledBounds[1], scaledBounds[3], scaledBounds[5], scaledBounds[0], scaledBounds[3], scaledBounds[5]);
  3165.         DrawSpaceLine(scaledBounds[0], scaledBounds[3], scaledBounds[5], scaledBounds[0], scaledBounds[2], scaledBounds[5]);
  3166.  
  3167.         /*Draw remaining sides*/
  3168.         DrawSpaceLine(scaledBounds[0], scaledBounds[2], scaledBounds[4], scaledBounds[0], scaledBounds[2], scaledBounds[5]);
  3169.         DrawSpaceLine(scaledBounds[1], scaledBounds[2], scaledBounds[4], scaledBounds[1], scaledBounds[2], scaledBounds[5]);
  3170.         DrawSpaceLine(scaledBounds[1], scaledBounds[3], scaledBounds[4], scaledBounds[1], scaledBounds[3], scaledBounds[5]);
  3171.         DrawSpaceLine(scaledBounds[0], scaledBounds[3], scaledBounds[4], scaledBounds[0], scaledBounds[3], scaledBounds[5]);
  3172.     }
  3173.  
  3174.     if (flags & (BBXMAJOR |    BBXMINOR | BBYMAJOR | BBYMINOR | BBZMAJOR | BBZMINOR))
  3175.     {
  3176.         /*Draw the tic marks*/
  3177.         ObjPtr var;
  3178.         real majorStep[3], nDivisions[3], ticLength[3];
  3179.         double maxSize;
  3180.         maxSize = bounds[1] - bounds[0];
  3181.         maxSize = MAX(bounds[3] - bounds[2], maxSize);
  3182.         maxSize = MAX(bounds[5] - bounds[4], maxSize);
  3183.  
  3184.         MakeVar(object, AXISMAJORSTEP);
  3185.         var = GetFixedArrayVar("DrawBounded", object, AXISMAJORSTEP, 1, 3L);
  3186.         if (var)
  3187.         {
  3188.         Array2CArray(majorStep, var);
  3189.         }
  3190.         else
  3191.         {
  3192.         majorStep[0] = majorStep[1] = majorStep[2] = 1.0;
  3193.         }
  3194.  
  3195.         MakeVar(object, AXISDIVISIONS);
  3196.         var = GetFixedArrayVar("DrawBounded", object, AXISDIVISIONS, 1, 3L);
  3197.         if (var)
  3198.         {
  3199.         Array2CArray(nDivisions, var);
  3200.         }
  3201.         else
  3202.         {
  3203.         nDivisions[0] = nDivisions[1] = nDivisions[2] = 1.0;
  3204.         }
  3205.  
  3206.         MakeVar(object, TICLENGTH);
  3207.         var = GetFixedArrayVar("DrawBounded", object, TICLENGTH, 1, 3L);
  3208.         if (var)
  3209.         {
  3210.         Array2CArray(ticLength, var);
  3211.         }
  3212.         else
  3213.         {
  3214.         ticLength[0] = ticLength[1] = ticLength[2] = 10.0;
  3215.         }
  3216.  
  3217.         SetUIFont(UIBOLDLARGEFONT);
  3218.  
  3219.         if ((flags & (BBXMAJOR | BBXMINOR)) && (bounds[1] > bounds[0]))
  3220.         {
  3221.         double majorWidth;
  3222.         int nTics;
  3223.         long temp;
  3224.         double minorWidth, curValue;
  3225.         int k;
  3226.  
  3227.         /*Do the x axis*/
  3228.         majorWidth = majorStep[0];
  3229.         minorWidth = majorWidth / nDivisions[0];
  3230.         nTics = nDivisions[0];
  3231.  
  3232.         temp = bounds[0] / majorWidth;
  3233.         curValue = temp * majorWidth;
  3234.  
  3235.         while (curValue > bounds[0])
  3236.         {
  3237.             curValue -= majorWidth;
  3238.         }
  3239.         k = 0;
  3240.  
  3241.         while (curValue < bounds[0])
  3242.         {
  3243.             ++k;
  3244.             if (k >= nTics) k = 0;
  3245.  
  3246.             curValue += minorWidth;
  3247.         }
  3248.  
  3249.         /*Now actually draw them*/
  3250.         if (ABS(curValue) < maxSize * 1.0E-6) curValue = 0.0;
  3251.         while (curValue <= bounds[1] + maxSize * 1.0E-6)
  3252.         {
  3253.             int strOff;
  3254.             if (k == 0 && (flags & BBXMAJOR))
  3255.             {
  3256.             /*Major tic*/
  3257.             SetUIColor(UIGRAY50);
  3258.                 DrawSpaceLine(curValue, bounds[2], bounds[4],
  3259.                        curValue, bounds[2] - ticLength[0],
  3260.                         bounds[4]);
  3261.             PrintNumber(tempStr, (real) curValue);
  3262.             DrawSpaceString(curValue, bounds[2] - ticLength[0] * LABELFACTOR,
  3263.                         bounds[4], tempStr);
  3264.             }
  3265.             else if (flags & BBXMINOR)
  3266.             {
  3267.             /*Minor tic*/
  3268.             SetUIColor(UIGRAY50);
  3269.                 DrawSpaceLine(curValue, bounds[2], bounds[4],
  3270.                        curValue, bounds[2] - ticLength[0] * MINORTICFACTOR,
  3271.                         bounds[4]);
  3272.             }
  3273.  
  3274.             curValue += minorWidth;
  3275.             if (ABS(curValue) < maxSize * 1.0E-6) curValue = 0.0;
  3276.             ++k;
  3277.             if (k >= nTics) k = 0;
  3278.         }
  3279.         }
  3280.         if ((flags & (BBYMAJOR | BBYMINOR)) && (bounds[3] > bounds[2]))
  3281.         {
  3282.         double majorWidth;
  3283.         int nTics;
  3284.         long temp;
  3285.         double minorWidth, curValue;
  3286.         int k;
  3287.  
  3288.         /*Do the y axis*/
  3289.         majorWidth = majorStep[1];
  3290.         minorWidth = majorWidth / nDivisions[1];
  3291.         nTics = nDivisions[1];
  3292.  
  3293.         temp = bounds[2] / majorWidth;
  3294.         curValue = temp * majorWidth;
  3295.  
  3296.         while (curValue > bounds[2])
  3297.         {
  3298.             curValue -= majorWidth;
  3299.         }
  3300.         k = 0;
  3301.  
  3302.         while (curValue < bounds[2])
  3303.         {
  3304.             ++k;
  3305.             if (k >= nTics) k = 0;
  3306.  
  3307.             curValue += minorWidth;
  3308.         }
  3309.  
  3310.         /*Now actually draw them*/
  3311.         if (ABS(curValue) < maxSize * 1.0E-6) curValue = 0.0;
  3312.         while (curValue <= bounds[3] + maxSize * 1.0E-6)
  3313.         {
  3314.             int strOff;
  3315.             if (k == 0 && (flags & BBYMAJOR))
  3316.             {
  3317.             /*Major tic*/
  3318.             SetUIColor(UIGRAY50);
  3319.                 DrawSpaceLine(bounds[0], curValue, bounds[4],
  3320.                        bounds[0] - ticLength[1], curValue,
  3321.                         bounds[4]);
  3322.             sprintf(tempStr, "%lg", curValue);
  3323.             DrawSpaceString(bounds[0] - ticLength[1] * LABELFACTOR, curValue,
  3324.                         bounds[4], tempStr);
  3325.             }
  3326.             else if (flags & BBYMINOR)
  3327.             {
  3328.             /*Minor tic*/
  3329.             SetUIColor(UIGRAY50);
  3330.                 DrawSpaceLine(bounds[0], curValue, bounds[4],
  3331.                        bounds[0] - ticLength[1] * MINORTICFACTOR, curValue,
  3332.                         bounds[4]);
  3333.             }
  3334.  
  3335.             curValue += minorWidth;
  3336.             if (ABS(curValue) < maxSize * 1.0E-6) curValue = 0.0;
  3337.             ++k;
  3338.             if (k >= nTics) k = 0;
  3339.         }
  3340.         }
  3341.         if ((flags & (BBZMAJOR | BBZMINOR)) && (bounds[5] > bounds[4]))
  3342.         {
  3343.         double majorWidth;
  3344.         int nTics;
  3345.         long temp;
  3346.         double minorWidth, curValue;
  3347.         int k;
  3348.  
  3349.         /*Do the z axis*/
  3350.         majorWidth = majorStep[2];
  3351.         minorWidth = majorWidth / nDivisions[2];
  3352.         nTics = nDivisions[2];
  3353.  
  3354.         temp = bounds[4] / majorWidth;
  3355.         curValue = temp * majorWidth;
  3356.  
  3357.         while (curValue > bounds[4])
  3358.         {
  3359.             curValue -= majorWidth;
  3360.         }
  3361.         k = 0;
  3362.  
  3363.         while (curValue < bounds[4])
  3364.         {
  3365.             ++k;
  3366.             if (k >= nTics) k = 0;
  3367.  
  3368.             curValue += minorWidth;
  3369.         }
  3370.  
  3371.         /*Now actually draw them*/
  3372.         if (ABS(curValue) < maxSize * 1.0E-6) curValue = 0.0;
  3373.         while (curValue <= bounds[5] + maxSize * 1.0E-6)
  3374.         {
  3375.             int strOff;
  3376.             if (k == 0 && (flags & BBZMAJOR))
  3377.             {
  3378.             /*Major tic*/
  3379.             SetUIColor(UIGRAY50);
  3380.                 DrawSpaceLine(bounds[0], bounds[2], curValue,
  3381.                        bounds[0] - ticLength[2],
  3382.                     bounds[2] - ticLength[2],
  3383.                         curValue);
  3384.             PrintNumber(tempStr, (real) curValue);
  3385.             DrawSpaceString(bounds[0] - ticLength[2] * LABELFACTOR,
  3386.                     bounds[2] - ticLength[2] * LABELFACTOR,
  3387.                         curValue, tempStr);
  3388.             }
  3389.             else if (flags & BBZMINOR)
  3390.             {
  3391.             /*Minor tic*/
  3392.             SetUIColor(UIGRAY50);
  3393.                 DrawSpaceLine(bounds[0], bounds[2], curValue,
  3394.                        bounds[0] - ticLength[2] * MINORTICFACTOR,
  3395.                     bounds[2] - ticLength[2] * MINORTICFACTOR,
  3396.                         curValue);
  3397.             }
  3398.  
  3399.             curValue += minorWidth;
  3400.             if (ABS(curValue) < maxSize * 1.0E-6) curValue = 0.0;
  3401.             ++k;
  3402.             if (k >= nTics) k = 0;
  3403.         }
  3404.         }
  3405.     }
  3406.     var = GetIntVar("DrawBounded", object, DRAWNAMES);
  3407.     if (var)
  3408.     {
  3409.         flags = GetInt(var);
  3410.     }
  3411.     else
  3412.     {
  3413.         flags = 0;
  3414.     }
  3415.     if (flags)
  3416.     {
  3417.         /*Draw the names of the axes*/
  3418.         SetUIColor(UIGRAY50);
  3419.             
  3420.         SetUIFont(UIBOLDLARGEFONT);
  3421.  
  3422.         if (flags & 1)
  3423.         {
  3424.         /*X axis*/
  3425.         MakeVar(object, XNAME);
  3426.         var = GetStringVar("DrawBounded", object, XNAME);
  3427.         DrawSpaceString((scaledBounds[1] + scaledBounds[0]) / 2.0,
  3428.          scaledBounds[2] - maxSize * AXISFACTOR,
  3429.          scaledBounds[4], var ? GetString(var) : "X");
  3430.         }
  3431.         
  3432.         if (flags & 2)
  3433.         {
  3434.         /*Y axis*/
  3435.         MakeVar(object, YNAME);
  3436.         var = GetStringVar("DrawBounded", object, YNAME);
  3437.         DrawSpaceString(scaledBounds[0] - maxSize * AXISFACTOR,
  3438.          (scaledBounds[3] + scaledBounds[2]) / 2.0,
  3439.          scaledBounds[4], var ? GetString(var) : "Y");
  3440.         }
  3441.  
  3442.         if (flags & 4)
  3443.         {
  3444.         /*Z axis*/
  3445.         MakeVar(object, ZNAME);
  3446.         var = GetStringVar("DrawBounded", object, ZNAME);
  3447.         DrawSpaceString(scaledBounds[0] - maxSize * AXISFACTOR,
  3448.          scaledBounds[2] - maxSize * AXISFACTOR,
  3449.          (scaledBounds[5] + scaledBounds[4]) / 2.0, var ? GetString(var) : "Z");
  3450.         }
  3451.     }
  3452.     NudgeFarther();
  3453.     }
  3454.     else
  3455.     {
  3456.     return ObjFalse;
  3457.     }
  3458. #endif
  3459.     return ObjTrue;
  3460. }
  3461.  
  3462. static ObjPtr MakeAxesMajorStep(object)
  3463. ObjPtr object;
  3464. /*Makes the axis major steps of an object*/
  3465. {
  3466.     double maxSize;
  3467.     real bounds[6];
  3468.     ObjPtr var;
  3469.     real *elements;
  3470.     double majorWidth;
  3471.     int nTics;
  3472.  
  3473.     GetBounds(object, bounds);
  3474.     maxSize = MAX(bounds[1] - bounds[0], MAX(bounds[3] - bounds[2], bounds[5] - bounds[4]));
  3475.  
  3476.     CalcGoodSteps(maxSize, 100, 10, &majorWidth, &nTics);
  3477.  
  3478.     var = NewRealArray(1, 3L);
  3479.     elements = ELEMENTS(var);
  3480.     elements[0] = majorWidth;
  3481.     elements[1] = majorWidth;
  3482.     elements[2] = majorWidth;
  3483.     SetVar(object, AXISMAJORSTEP, var);
  3484.     return ObjTrue;
  3485. }
  3486.  
  3487. static ObjPtr MakeAxesDivisions(object)
  3488. ObjPtr object;
  3489. /*Makes the axis divisions of an object*/
  3490. {
  3491.     double maxSize;
  3492.     real bounds[6];
  3493.     ObjPtr var;
  3494.     real *elements;
  3495.     double majorWidth;
  3496.     int nTics;
  3497.  
  3498.     GetBounds(object, bounds);
  3499.     maxSize = MAX(bounds[1] - bounds[0], MAX(bounds[3] - bounds[2], bounds[5] - bounds[4]));
  3500.  
  3501.     CalcGoodSteps(maxSize, 100, 10, &majorWidth, &nTics);
  3502.  
  3503.     var = NewRealArray(1, 3L);
  3504.     elements = ELEMENTS(var);
  3505.     elements[0] = nTics;
  3506.     elements[1] = nTics;
  3507.     elements[2] = nTics;
  3508.     SetVar(object, AXISDIVISIONS, var);
  3509.     return ObjTrue;
  3510. }
  3511.  
  3512.  
  3513. static ObjPtr DrawWalls(object)
  3514. ObjPtr object;
  3515. /*Draw walls around a bounded object.  No, that's done in VisObj*/
  3516. {
  3517.     return ObjTrue;
  3518. }
  3519.  
  3520. static ObjPtr MakePicColored(object)
  3521. ObjPtr object;
  3522. /*Makes the picture object in object colored*/
  3523. {
  3524.     ObjPtr colorObj;
  3525.     ObjPtr surface;
  3526.  
  3527.     MakeVar(object, SURFACE);
  3528.     surface = GetVar(object, SURFACE);
  3529.     if (!surface) return ObjFalse;
  3530.     /*Make it colored or not according to COLORS and COLOROBJ*/
  3531.     if (GetPredicate(object, COLORS) && (colorObj = GetVar(object, COLOROBJ)))
  3532.     {
  3533.     /*Have to make it colored by the object*/
  3534.     ObjPtr cPalette;
  3535.  
  3536.     MakeVar(object, CPALETTE);
  3537.     cPalette = GetPaletteVar("MakePicColored", object, CPALETTE);
  3538.     if (cPalette)
  3539.     {
  3540.         SetPalette(cPalette);
  3541.         ColorPictureByObject(surface, colorObj, GetPredicate(object, INTERPCOLORS));
  3542.     }
  3543.     }
  3544.     SetVar(object, PICCOLORED, ObjTrue);
  3545.     return ObjTrue;
  3546. }
  3547.  
  3548. static ObjPtr MakePicDeformed(object)
  3549. ObjPtr object;
  3550. /*Makes the picture object in object deformed*/
  3551. {
  3552.     ObjPtr surface;
  3553.  
  3554.     MakeVar(object, SURFACE);
  3555.     surface = GetPictureVar("MakePicDeformed", object, SURFACE);
  3556.     if (!surface) return ObjFalse;
  3557.  
  3558.     SetupDeformation(object);
  3559.  
  3560.     /*Make it deformed or not*/
  3561.     DeformPictureByObject(surface);
  3562.  
  3563.     SetVar(object, PICDEFORMED, ObjTrue);
  3564.     return ObjTrue;
  3565. }
  3566.  
  3567. static ObjPtr MakeGeoPicColored(object)
  3568. ObjPtr object;
  3569. /*Makes the picture object in object colored*/
  3570. {
  3571.     ObjPtr colorObj;
  3572.     ObjPtr surface;
  3573.     ObjPtr cPalette;
  3574.  
  3575.     MakeVar(object, CPALETTE);
  3576.     cPalette = GetPaletteVar("MakeGeoPicColored", object, CPALETTE);
  3577.     if (cPalette)
  3578.     {
  3579.     SetPalette(cPalette);
  3580.     }
  3581.  
  3582.     surface = GetPictureVar("MakeGeoPicColored", object, SURFACE);
  3583.     if (!surface) return ObjFalse;
  3584.  
  3585.     /*Make it colored or not according to COLORS and COLOROBJ*/
  3586.     if (GetPredicate(object, COLORS) && (colorObj = GetVar(object, COLOROBJ)))
  3587.     {
  3588.     /*Have to make it colored by the object*/
  3589.     if (colorObj == GetVar(object, REPOBJ))
  3590.     {
  3591.         ObjPtr data, eternalData, var;
  3592.         /*Color it by itself*/
  3593.  
  3594.         SetCurField(FIELD1, colorObj);
  3595.         data = curFields[FIELD1] . objectInfo;
  3596.  
  3597.         eternalData = GetVar(colorObj, ETERNALPART);
  3598.         if (eternalData)
  3599.         {
  3600.         PicItemPtr curItems, destItems;
  3601.  
  3602.         destItems = ((PicPtr) surface) -> items;
  3603.  
  3604.         curItems = ((PicPtr) eternalData) -> items;
  3605.         destItems = ColorItemsByItems(destItems, object, curItems);
  3606.  
  3607.         curItems = ((PicPtr) data) -> items;
  3608.         destItems = ColorItemsByItems(destItems, object, curItems);
  3609.         }
  3610.         else
  3611.         {
  3612.         ColorPictureByPicture(surface, object, data);
  3613.         }
  3614.     }
  3615.     else
  3616.     {
  3617.         ColorPictureByObject(surface, colorObj, GetPredicate(object, INTERPCOLORS));
  3618.     }
  3619.     }
  3620.     SetVar(object, PICCOLORED, ObjTrue);
  3621.     return ObjTrue;
  3622. }
  3623.  
  3624. static ObjPtr DrawVisSurface(object)
  3625. ObjPtr object;
  3626. /*Draw a surface vis object, by default, gets picture*/
  3627. {
  3628. #ifdef GRAPHICS
  3629.     ObjPtr repObj;
  3630.  
  3631.     if ((!drawSolid) && GetPredicate(object, ISTRANSPARENT) != drawingTransparent)
  3632.     {
  3633.     /*Don't draw if not the same pass*/
  3634.     return ObjFalse;
  3635.     }
  3636.  
  3637.     /*Get the object's main dataset*/
  3638.     repObj = GetVar(object, MAINDATASET);
  3639.     if (!repObj) repObj = GetObjectVar("DrawVisSurface", object, REPOBJ);
  3640.     if (repObj)
  3641.     {
  3642.     Bool drawSurface;
  3643.     real baseColor[3];        /*Base color of the object*/
  3644.     ObjPtr var;
  3645.     ObjPtr surface;
  3646.     ObjPtr colors;
  3647.  
  3648.     drawSurface = GetPredicate(object, DRAWSURFACE);
  3649.     if (drawSurface)
  3650.     {
  3651.         if (DQ_FULL < minDrawingQuality ||
  3652.         DQ_FULL > maxDrawingQuality)
  3653.         {
  3654.         drawSurface = false;
  3655.         }
  3656.     }
  3657.     else if (maxDrawingQuality == DQ_FULL &&
  3658.          qualityDrawnSoFar <= DQ_MIN)
  3659.     {
  3660.         /*Surface is at the top, draw it anyway*/
  3661.         drawSurface = true;
  3662.     }
  3663.  
  3664.     if (!drawSurface)
  3665.     {
  3666.         /*Nothing to draw, return*/
  3667.         return ObjFalse;
  3668.     }
  3669.  
  3670.     if (drawSurface)
  3671.     {
  3672.         qualityDrawnSoFar = MAX(qualityDrawnSoFar, DQ_FULL);
  3673.     }
  3674.  
  3675.     var = GetVar(object, BASECOLOR);
  3676.     if (var)
  3677.     {
  3678.         Array2CArray(baseColor, var);
  3679.     }
  3680.     else
  3681.     {
  3682.         baseColor[0] = 1.0;
  3683.         baseColor[1] = 1.0;
  3684.         baseColor[2] = 1.0;
  3685.     }
  3686.  
  3687.     MakeVar(object, CPALETTE);
  3688.     colors = GetVar(object, CPALETTE);
  3689.     if (!colors)
  3690.     {
  3691.         return ObjFalse;
  3692.     }
  3693.  
  3694.     /*Get the surface*/
  3695.     MakeVar(object, SURFACE);
  3696.     surface = GetVar(object, SURFACE);
  3697.     if (!surface)
  3698.     {
  3699.         return ObjFalse;
  3700.     }
  3701.  
  3702.     /*Set the palette for subsequent draws*/
  3703.     SetPalette(colors);
  3704.  
  3705.     if (drawSurface)
  3706.     {
  3707.         /*OK, so everything exists.  Fine.  Now draw it.*/
  3708.         real specular, shininess, brightness;
  3709.         int lightShading, colorShading;
  3710.         int matIndex;
  3711.         real specColor[3];
  3712.  
  3713.         /*Get the light shading of the surface*/
  3714.         MakeVar(object, LIGHTSHADING);
  3715.         var = GetVar(object, LIGHTSHADING);
  3716.         if (var)
  3717.         {
  3718.         lightShading = GetInt(var);
  3719.         }
  3720.         else
  3721.         {
  3722.         lightShading = NOLIGHT;
  3723.         }
  3724.  
  3725.         /*Get the color shading of the surface*/
  3726.         if (GetPredicate(object, COLORS) && GetVar(object, COLOROBJ))
  3727.         {
  3728.         /*There is a color field.  Shade according to value of COLORSHADING*/
  3729.         colorShading = GetPredicate(object, COLORSHADING) ? SMOOTHCOLOR : MONOCOLOR;
  3730.         }
  3731.         else
  3732.         {
  3733.         /*There is no color field.  Shade to nocolors.*/
  3734.         colorShading = NOCOLOR;
  3735.         }
  3736.  
  3737.         /*Make the material*/
  3738.         var = GetVar(object, SPECVAL);
  3739.         if (var && IsReal(var))
  3740.         {
  3741.         specular = GetReal(var);
  3742.         }
  3743.         else
  3744.         {
  3745.         specular = 0.2;
  3746.         }
  3747.         var = GetVar(object, HIGHLIGHTCOLOR);
  3748.         if (var && IsRealArray(var) && RANK(var) == 1 && DIMS(var)[0] == 3)
  3749.         {
  3750.         Array2CArray(specColor, var);
  3751.         specColor[0] *= specular;
  3752.         specColor[1] *= specular;
  3753.         specColor[2] *= specular;
  3754.         }
  3755.         else
  3756.         {
  3757.         specColor[0] = specular;
  3758.         specColor[1] = specular;
  3759.         specColor[2] = specular;
  3760.         }
  3761.         var = GetVar(object, SHINVAL);
  3762.         if (var && IsReal(var))
  3763.         {
  3764.         shininess = GetReal(var);
  3765.         }
  3766.         else
  3767.         {
  3768.         shininess = 80.0;
  3769.         }
  3770.         var = GetVar(object, BRIGHTNESS);
  3771.         if (var && IsReal(var))
  3772.         {
  3773.         brightness = GetReal(var);
  3774.         }
  3775.         else
  3776.         {
  3777.         brightness = 1.0;
  3778.         }
  3779.  
  3780.         matIndex = 0;
  3781.         material[matIndex++] = SPECULAR;
  3782.         material[matIndex++] = specColor[0];
  3783.         material[matIndex++] = specColor[1];
  3784.         material[matIndex++] = specColor[2];
  3785.         material[matIndex++] = SHININESS;
  3786.         material[matIndex++] = shininess;
  3787.         material[matIndex++] = DIFFUSE;
  3788.         material[matIndex++] = baseColor[0] * brightness;
  3789.         material[matIndex++] = baseColor[1] * brightness;
  3790.         material[matIndex++] = baseColor[2] * brightness;
  3791.         material[matIndex++] = LMNULL;
  3792.  
  3793.         lmdef(DEFMATERIAL, VISMATERIAL, matIndex, material);
  3794.         if (rgbp)
  3795.         {
  3796.         lmbind(MATERIAL, VISMATERIAL);
  3797.         }
  3798.  
  3799.         if ((!drawSolid) && GetPredicate(object, ISTRANSLUCENT))
  3800.         {
  3801.         BeginTranslucent();
  3802.         }
  3803.  
  3804.         /*Set the lighting model*/
  3805.         if (GetPredicate(object, TWOSIDEDSURFACE))
  3806.         {
  3807.         TwoSided(true);
  3808.         }
  3809.  
  3810.         if (hasDithering)
  3811.         {
  3812. #ifdef DT_ON
  3813.         dither(DT_ON);
  3814. #endif
  3815.         }
  3816.         /*Make sure it's colored*/
  3817.         MakeVar(object, PICCOLORED);
  3818.  
  3819.         drawingQuality = DQ_FULL;
  3820.         DrawPicture(surface, drawingTransparent, lightShading, colorShading, colors);
  3821.         if (hasDithering)
  3822.         {
  3823. #ifdef DT_OFF
  3824.         dither(DT_OFF);
  3825. #endif
  3826.         }
  3827.         if (GetPredicate(object, TWOSIDEDSURFACE))
  3828.         {
  3829.         TwoSided(false);
  3830.         }
  3831.         if ((!drawSolid) && GetPredicate(object, ISTRANSLUCENT))
  3832.         {
  3833.         EndTranslucent();
  3834.         }
  3835.  
  3836.         lmcolor(LMC_COLOR);
  3837.     }
  3838.     }
  3839.     else
  3840.     {
  3841.     return ObjFalse;
  3842.     }
  3843. #endif
  3844.     return ObjTrue;
  3845. }
  3846.  
  3847. static ObjPtr DrawVisLines(object)
  3848. ObjPtr object;
  3849. /*Draw the lines of a surface vis object, by default, gets picture*/
  3850. {
  3851. #ifdef GRAPHICS
  3852.     ObjPtr repObj;
  3853.  
  3854.     if (drawingTransparent)
  3855.     {
  3856.     /*Don't draw on transparent pass*/
  3857.     return ObjFalse;
  3858.     }
  3859.  
  3860.     /*Get the object's main dataset*/
  3861.     repObj = GetVar(object, MAINDATASET);
  3862.     if (!repObj) repObj = GetObjectVar("DrawVisLines", object, REPOBJ);
  3863.     if (repObj)
  3864.     {
  3865.     Bool drawWireFrame;
  3866.     real baseColor[3];        /*Base color of the object*/
  3867.     ObjPtr var;
  3868.     ObjPtr surface;
  3869.     ObjPtr colors;
  3870.     int colorShading;
  3871.     Bool antiAlias = false;
  3872.  
  3873.     /*Get the color shading of the surface*/
  3874.     MakeVar(object, COLORSHADING);
  3875.     /*Get the color shading of the surface*/
  3876.     if (GetPredicate(object, COLORS) && GetVar(object, COLOROBJ))
  3877.     {
  3878.         /*There is a color field.  Shade according to value of COLORSHADING*/
  3879.         colorShading = GetPredicate(object, COLORSHADING) ? SMOOTHCOLOR : MONOCOLOR;
  3880.     }
  3881.     else
  3882.     {
  3883.         /*There is no color field.  Shade to nocolors.*/
  3884.         colorShading = NOCOLOR;
  3885.     }
  3886.  
  3887.     drawWireFrame = GetPredicate(object, DRAWWIREFRAME);
  3888.     if (drawWireFrame)
  3889.     {
  3890.         /*If it's outside the range, don't draw a thing*/
  3891.         if (DQ_WIREFRAME < minDrawingQuality ||
  3892.         DQ_WIREFRAME > maxDrawingQuality)
  3893.         {
  3894.         drawWireFrame = false;
  3895.         }
  3896.     }
  3897.     else if (maxDrawingQuality == DQ_WIREFRAME &&
  3898.          qualityDrawnSoFar <= DQ_MIN)
  3899.     {
  3900.         /*Wire frame is the top, draw it anyway*/
  3901.         drawWireFrame = true;
  3902.     }
  3903.  
  3904.     if (!drawWireFrame)
  3905.     {
  3906.         /*Nothing to draw, return*/
  3907.         return ObjFalse;
  3908.     }
  3909.  
  3910.     if (drawWireFrame)
  3911.     {
  3912.         qualityDrawnSoFar = MAX(qualityDrawnSoFar, DQ_WIREFRAME);
  3913.     }
  3914.  
  3915.     var = GetVar(object, BASECOLOR);
  3916.     if (var)
  3917.     {
  3918.         Array2CArray(baseColor, var);
  3919.     }
  3920.     else
  3921.     {
  3922.         baseColor[0] = 1.0;
  3923.         baseColor[1] = 1.0;
  3924.         baseColor[2] = 1.0;
  3925.     }
  3926.  
  3927.     MakeVar(object, CPALETTE);
  3928.     colors = GetVar(object, CPALETTE);
  3929.     if (!colors)
  3930.     {
  3931.         return ObjFalse;
  3932.     }
  3933.  
  3934.     /*Get the surface*/
  3935.     surface = GetVar(object, SURFACE);
  3936.     MakeVar(object, SURFACE);
  3937.     if (!surface)
  3938.     {
  3939.         return ObjFalse;
  3940.     }
  3941.  
  3942.     /*Set the palette for subsequent draws*/
  3943.     SetPalette(colors);
  3944.  
  3945.     var = GetVar(object, LINEWIDTH);
  3946.     if (var)
  3947.     {
  3948.         int width;
  3949.         width = GetReal(var);
  3950.         if (width < 1) width = 1;
  3951.         SetLineWidth(width);
  3952.     }
  3953.  
  3954.     if (hasAntialiasedLines && rgbp && GetPredicate(object, ANTIALIASLINES))
  3955.     {
  3956.         linesmooth(SML_ON);
  3957.         blendfunction(BF_SA, BF_MSA);
  3958.         subpixel(TRUE);
  3959.         antiAlias = true;
  3960.     }
  3961.  
  3962.     /*Make sure it's colored*/
  3963.     MakeVar(object, PICCOLORED);
  3964.  
  3965.     drawingQuality = DQ_WIREFRAME;
  3966.     NudgeCloser();
  3967.     NudgeCloser();
  3968.     DrawPicture(surface, drawingTransparent, GetPredicate(object, DEPTHCUELINES) ? DEPTHCUELIGHT : NOLIGHT, colorShading, colors);
  3969.     NudgeFarther();
  3970.     NudgeFarther();
  3971.  
  3972.     SetLineWidth(1);
  3973.     if (antiAlias)
  3974.     {
  3975.         linesmooth(SML_OFF);
  3976.         blendfunction(BF_ONE, BF_ZERO);
  3977.         subpixel(FALSE);
  3978.     }
  3979.     }
  3980.     else
  3981.     {
  3982.     return ObjFalse;
  3983.     }
  3984. #endif
  3985.     return ObjTrue;
  3986. }
  3987.  
  3988. static ObjPtr PickVisDots(object)
  3989. ObjPtr object;
  3990. /*Draws all the dots in an object for picking*/
  3991. {
  3992.     ObjPtr picture;
  3993.  
  3994.     MakeVar(object, SURFACE);
  3995.     picture = GetVar(object, SURFACE);
  3996.     if (picture)
  3997.     {
  3998.     PickCanonicalPictureVertices(picture);
  3999.     }
  4000.     return ObjTrue;
  4001. }
  4002.  
  4003. static ObjPtr DrawVisDots(object)
  4004. ObjPtr object;
  4005. /*Draw the dots of a surface vis object, by default, gets picture*/
  4006. {
  4007. #ifdef GRAPHICS
  4008.     ObjPtr repObj;
  4009.  
  4010.     if (drawingTransparent)
  4011.     {
  4012.     /*Don't draw on transparent pass*/
  4013.     return ObjFalse;
  4014.     }
  4015.  
  4016.     /*Get the object's main dataset*/
  4017.     repObj = GetVar(object, MAINDATASET);
  4018.     if (!repObj) repObj = GetObjectVar("DrawVisLines", object, REPOBJ);
  4019.     if (repObj)
  4020.     {
  4021.     Bool drawDots;
  4022.     real baseColor[3];        /*Base color of the object*/
  4023.     ObjPtr var;
  4024.     ObjPtr surface;
  4025.     ObjPtr colors;
  4026.     int colorShading;
  4027.     Bool antiAlias = false;
  4028.     Bool biggerDots = false;
  4029.  
  4030.     /*Get the color shading of the surface*/
  4031.     MakeVar(object, COLORSHADING);
  4032.     /*Get the color shading of the surface*/
  4033.     if (GetPredicate(object, COLORS) && GetVar(object, COLOROBJ))
  4034.     {
  4035.         /*There is a color field.  Shade according to value of COLORSHADING*/
  4036.         colorShading = GetPredicate(object, COLORSHADING) ? SMOOTHCOLOR : MONOCOLOR;
  4037.     }
  4038.     else
  4039.     {
  4040.         /*There is no color field.  Shade to nocolors.*/
  4041.         colorShading = NOCOLOR;
  4042.     }
  4043.  
  4044.     drawDots = GetPredicate(object, DRAWDOTS);
  4045.     if (drawDots)
  4046.     {
  4047.         /*If it's outside the range, don't draw a thing*/
  4048.         if (DQ_DOTS < minDrawingQuality ||
  4049.         DQ_DOTS > maxDrawingQuality)
  4050.         {
  4051.         drawDots = false;
  4052.         }
  4053.     }
  4054.     else if (maxDrawingQuality == DQ_DOTS &&
  4055.          qualityDrawnSoFar <= DQ_MIN)
  4056.     {
  4057.         /*Dots is the top, draw it anyway*/
  4058.         drawDots = true;
  4059.     }
  4060.  
  4061.     if (!drawDots)
  4062.     {
  4063.         /*Nothing to draw, return*/
  4064.         return ObjFalse;
  4065.     }
  4066.  
  4067.     qualityDrawnSoFar = MAX(qualityDrawnSoFar, DQ_DOTS);
  4068.  
  4069.     var = GetVar(object, BASECOLOR);
  4070.     if (var)
  4071.     {
  4072.         Array2CArray(baseColor, var);
  4073.     }
  4074.     else
  4075.     {
  4076.         baseColor[0] = 1.0;
  4077.         baseColor[1] = 1.0;
  4078.         baseColor[2] = 1.0;
  4079.     }
  4080.  
  4081.     MakeVar(object, CPALETTE);
  4082.     colors = GetVar(object, CPALETTE);
  4083.     if (!colors)
  4084.     {
  4085.         return ObjFalse;
  4086.     }
  4087.  
  4088.     /*Get a surface*/
  4089.     MakeVar(object, SURFACE);
  4090.     surface = GetVar(object, SURFACE);
  4091.     if (!surface)
  4092.     {
  4093.         return ObjFalse;
  4094.     }
  4095.  
  4096.     /*Set the palette for subsequent draws*/
  4097.     SetPalette(colors);
  4098.  
  4099.  
  4100.     if (hasAntialiasedPoints && rgbp && GetPredicate(object, ANTIALIASDOTS))
  4101.     {
  4102.         pntsmooth(SML_ON);
  4103.         blendfunction(BF_SA, BF_MSA);
  4104.         subpixel(TRUE);
  4105.         antiAlias = true;
  4106.     }
  4107.  
  4108.     if (GetPredicate(object, BIGGERDOTS))
  4109.     {
  4110.         SetPointWidth(2);
  4111.         biggerDots = 0;
  4112.     }
  4113.     else
  4114.     {
  4115.         SetPointWidth(1);
  4116.     }
  4117.     /*Make sure it's colored*/
  4118.     MakeVar(object, PICCOLORED);
  4119.  
  4120.     drawingQuality = DQ_DOTS;
  4121.     NudgeCloser();
  4122.     NudgeCloser();
  4123.     DrawPicture(surface, drawingTransparent, GetPredicate(object, DEPTHCUEDOTS) ? DEPTHCUELIGHT : NOLIGHT, colorShading, colors);
  4124.     NudgeFarther();
  4125.     NudgeFarther();
  4126.  
  4127.     if (antiAlias)
  4128.     {
  4129.         pntsmooth(SML_OFF);
  4130.         blendfunction(BF_ONE, BF_ZERO);
  4131.         subpixel(FALSE);
  4132.     }
  4133.  
  4134.     if (biggerDots)
  4135.     {
  4136.         SetPointWidth(1);
  4137.     }
  4138.     }
  4139.     else
  4140.     {
  4141.     return ObjFalse;
  4142.     }
  4143. #endif
  4144.     return ObjTrue;
  4145. }
  4146.  
  4147. static ObjPtr MakeGeoPictureSurface(object)
  4148. ObjPtr object;
  4149. /*Makes a geopicture's surface*/
  4150. {
  4151.     ObjPtr repObj;
  4152.     ObjPtr picture;
  4153.     ObjPtr newPic;
  4154.     ObjPtr data;
  4155.     ObjPtr eternalData;
  4156.     long flags;
  4157.     ObjPtr var;
  4158.  
  4159.     repObj = GetObjectVar("MakeGeoPictureSurface", object, REPOBJ);
  4160.     if (!repObj)
  4161.     {
  4162.     return ObjFalse;
  4163.     }
  4164.  
  4165.     SetCurField(FIELD1, repObj);
  4166.  
  4167.     flags = GetDatasetInfo(repObj);
  4168.     if (flags & DS_HASGEOMETRY)
  4169.     {
  4170.     picture = curFields[FIELD1] . objectInfo;
  4171.  
  4172.     eternalData = GetVar(repObj, ETERNALPART);
  4173.  
  4174.     if (eternalData)
  4175.     {
  4176.         newPic = ConvertPicture(eternalData, object);
  4177.         if (picture)
  4178.         {
  4179.         ConvertOntoPicture(newPic, picture, object);
  4180.         }
  4181.         SetVar(object, SURFACE, newPic);
  4182.     }
  4183.     else
  4184.     {
  4185.         if (picture)
  4186.         {
  4187.         SetVar(object, SURFACE, newPic = ConvertPicture(picture, object));
  4188.         }
  4189.     }
  4190.     SetVar(newPic, REPOBJ, object);
  4191.     }
  4192.     else if (flags & DS_HASNEWGEOMETRY)
  4193.     {
  4194.     /*It's a new geometry*/
  4195.     newPic = ConvertDatasetToPicture(repObj, GetVar(object, NORMALSOBJ));
  4196.     SetVar(object, SURFACE, newPic);
  4197.     SetVar(newPic, REPOBJ, object);
  4198.     SetVar(newPic, MAINDATASET, repObj);
  4199.     }
  4200.  
  4201.     return ObjTrue;
  4202. }
  4203.  
  4204. static ObjPtr MakeColoredPalette(object)
  4205. ObjPtr object;
  4206. /*Makes a palette in a color object*/
  4207. {
  4208.     ObjPtr palette;
  4209.     ObjPtr var;
  4210.     real brightness;
  4211.     ObjPtr colors;
  4212.  
  4213.     /*Make a palette if none exists*/
  4214.     palette = GetVar(object, CPALETTE);
  4215.     if (!palette)
  4216.     {
  4217.     palette = NewPalette(DEFPALSIZE);
  4218.     }
  4219.     SetVar(object, CPALETTE, palette);
  4220.  
  4221.     /*Get the brightness*/
  4222.     var = GetVar(object, BRIGHTNESS);
  4223.     if (var && IsReal(var))
  4224.     {
  4225.     brightness = GetReal(var);
  4226.     }
  4227.     else
  4228.     {
  4229.     brightness = 1.0;
  4230.     }
  4231.  
  4232.     /*Get the colors of the field*/
  4233.     if (GetPredicate(object, COLORS) && (colors = GetVar(object, COLOROBJ)))
  4234.     {
  4235.     /*It gets its colors from a field.*/
  4236.     ObjPtr sourcePalette;
  4237.  
  4238.     MakeVar(colors, CPALETTE);
  4239.     
  4240.     sourcePalette = GetVar(colors, CPALETTE);
  4241.     if (!sourcePalette)
  4242.     {
  4243.         return ObjFalse;
  4244.     }
  4245.  
  4246.     CopyAttenuatedPalette(palette, sourcePalette, brightness);
  4247.     }
  4248.     else
  4249.     {
  4250.     real rgb[3];
  4251.     /*Assume it's going to be a plain ramp to BASECOLOR*/
  4252.  
  4253.     /*Get the color*/
  4254.     var = GetVar(object, BASECOLOR);
  4255.     if (var && IsRealArray(var) && RANK(var) == 1 && DIMS(var)[0] == 3)
  4256.     {
  4257.         Array2CArray(rgb, var);
  4258.     }
  4259.     else
  4260.     {
  4261.         rgb[0] = rgb[1] = rgb[2] = 1.0;
  4262.     }
  4263.     SetPaletteMinMax(palette, -1.0, 1.0);
  4264.     InterpPalette(palette, 0, 0, 0,
  4265.              (int) (255.0 * brightness * rgb[0]),
  4266.              (int) (255.0 * brightness * rgb[1]),
  4267.              (int) (255.0 * brightness * rgb[2]));
  4268.     }
  4269.     return ObjTrue;
  4270. }
  4271.  
  4272. static ObjPtr HideVisObject(object)
  4273. ObjPtr object;
  4274. /*Hides a vis object*/
  4275. {
  4276.     SetVar(object, HIDDEN, ObjTrue);
  4277.     ImInvalid(object);
  4278.     return ObjTrue;
  4279. }
  4280.  
  4281. static ObjPtr ShowVisObject(object)
  4282. ObjPtr object;
  4283. /*Shows a vis object*/
  4284. {
  4285.     SetVar(object, HIDDEN, ObjFalse);
  4286.     ImInvalid(object);
  4287.     return ObjTrue;
  4288. }
  4289.  
  4290. static ObjPtr replaceList;
  4291.  
  4292. #ifdef PROTO
  4293. static void RVHelper(VarsPtr vars, ObjPtr oldVal, ObjPtr newVal)
  4294. #else
  4295. static void RVHelper(vars, oldVal, newVal)
  4296. VarsPtr vars;
  4297. ObjPtr oldVal;
  4298. ObjPtr newVal;
  4299. #endif
  4300. /*Helper for ReplaceVars, puts symbols to replace on replaceList*/
  4301. {
  4302.     if (vars)
  4303.     {
  4304.     if (vars -> value == oldVal)
  4305.     {
  4306.         PrefixList(replaceList, NewSymbol(vars -> name));
  4307.     }
  4308.     RVHelper(vars -> left, oldVal, newVal);
  4309.     RVHelper(vars -> right, oldVal, newVal);
  4310.     }
  4311. }
  4312.  
  4313. #ifdef PROTO
  4314. static void ReplaceVars(ObjPtr object, ObjPtr oldVal, ObjPtr newVal)
  4315. #else
  4316. static void ReplaceVars(object, oldVal, newVal)
  4317. ObjPtr object, oldVal, newVal;
  4318. #endif
  4319. /*For an object, replaces all top level vars with value oldVal to be
  4320.   newVal*/
  4321. {
  4322.     ThingListPtr runner;
  4323.     NameTyp id;
  4324.  
  4325.     replaceList = NewList();
  4326.  
  4327.     RVHelper(object -> vars, oldVal, newVal);
  4328.  
  4329.     runner = LISTOF(replaceList);
  4330.     while (runner)
  4331.     {
  4332.     if (IsSymbol(runner -> thing))
  4333.     {
  4334.         id = GetSymbolID(runner -> thing);
  4335.         SetVar(object, id, newVal);
  4336.     }
  4337.     runner = runner -> next;
  4338.     }
  4339. }
  4340.  
  4341. static ObjPtr CloneVisObject(visObj)
  4342. ObjPtr visObj;
  4343. /*Clones a visualization object*/
  4344. {
  4345.     FuncTyp method;
  4346.     ObjPtr newVis;
  4347.     ObjPtr palette;
  4348.     ObjPtr mainDataset;
  4349.  
  4350.     newVis = Clone(visObj);
  4351.     
  4352.     MakeVar(visObj, CPALETTE);
  4353.     palette = GetVar(visObj, CPALETTE);
  4354.     if (palette)
  4355.     {
  4356.     SetVar(newVis, CPALETTE, ClonePalette(palette));
  4357.     }
  4358.  
  4359.     mainDataset = GetVar(newVis, MAINDATASET);
  4360.     if (mainDataset)
  4361.     {
  4362.     /*Clone main dataset*/
  4363.     method = GetMethod(mainDataset, CLONE);
  4364.     if (method)
  4365.     {
  4366.         ReplaceVars(newVis, mainDataset, (*method)(mainDataset));
  4367.     }
  4368.     }
  4369.     return newVis;
  4370. }
  4371.  
  4372. static ObjPtr PrefixMainDataset(list, visObject)
  4373. ObjPtr list, visObject;
  4374. /*Prefixes the datasets from MAINDATASET or REPOBJ to list*/
  4375. {
  4376.     ObjPtr mainDataSet;
  4377.     mainDataSet = GetVar(visObject, MAINDATASET);
  4378.     if (!mainDataSet) mainDataSet = GetVar(visObject, REPOBJ);
  4379.     if (mainDataSet)
  4380.     {
  4381.     PrefixList(list, mainDataSet);
  4382.     }
  4383. }
  4384.  
  4385. void PrefixDatasets(list, visObject)
  4386. ObjPtr list, visObject;
  4387. /*Prefixes all datastes that visObject uses to list*/
  4388. {
  4389.     FuncTyp method;
  4390.     ObjPtr class;
  4391.  
  4392.     class = visObject;
  4393.     while (class)
  4394.     {
  4395.     method = Get1Method(class, PREFIXDATASETS);
  4396.     if (method)
  4397.     {
  4398.         (*method)(list, visObject);
  4399.     }
  4400.     class = ClassOf(class);
  4401.     }
  4402. }
  4403.  
  4404. ObjPtr MakeBoundedTicLength(object)
  4405. ObjPtr object;
  4406. /*Makes an object's tic length*/
  4407. {
  4408.     ObjPtr var;
  4409.     real maxSize;
  4410.     real *elements;
  4411.  
  4412.     real bounds[6];
  4413.     GetBounds(object, bounds);
  4414.  
  4415.     maxSize = bounds[1] - bounds[0];
  4416.     maxSize = MAX(maxSize, bounds[3] - bounds[2]);
  4417.     maxSize = MAX(maxSize, bounds[5] - bounds[4]);
  4418.  
  4419.     var = NewRealArray(1, 3L);
  4420.     elements = ELEMENTS(var);
  4421.     elements[0] = elements[1] = elements[2] = maxSize * MAJORTICSIZE;
  4422.     SetVar(object, TICLENGTH, var);
  4423.  
  4424.     return ObjTrue;
  4425. }
  4426.  
  4427. static ObjPtr AddGeometryControls(geometry, panelContents)
  4428. ObjPtr geometry, panelContents;
  4429. /*Adds controls appropriate to a geometry object to panelContents*/
  4430. {
  4431.     ObjPtr titleBox, button, radio, var, corral, icon, name;
  4432.     ObjPtr textBox, defaultIcon;
  4433.     int width, left, top, bottom, right;
  4434.     int bw;
  4435.  
  4436.     width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
  4437.  
  4438.     left = MAJORBORDER;
  4439.     top = CWINHEIGHT - MAJORBORDER;
  4440.  
  4441.     /*Make sphere controls*/
  4442.     right = PICSPHEREBOXWID + left;
  4443.     bottom = top - TITLEBOXTOP - 2 * MINORBORDER - 2 * CHECKBOXSPACING - 3 * CHECKBOXHEIGHT;
  4444.     titleBox = NewTitleBox(left, right,
  4445.         bottom, top,
  4446.         "Spheres");
  4447.     PrefixList(panelContents, titleBox);
  4448.     SetVar(titleBox, PARENT, panelContents);
  4449.  
  4450.     /*Make the sphere radio button group*/
  4451.     radio = NewRadioButtonGroup("Sphere Facet Group");
  4452.     PrefixList(panelContents, radio);
  4453.     SetVar(radio, PARENT, panelContents);
  4454.     top -= TITLEBOXTOP + MINORBORDER;
  4455.  
  4456.     /*Make the buttons*/
  4457.     button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
  4458.                 top - CHECKBOXHEIGHT, top, "8 facets");
  4459.     AddRadioButton(radio, button);
  4460.  
  4461.     button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
  4462.                 top - 2 * CHECKBOXHEIGHT - CHECKBOXSPACING,
  4463.                 top - CHECKBOXHEIGHT - CHECKBOXSPACING, "32 facets");
  4464.     AddRadioButton(radio, button);
  4465.  
  4466.     button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
  4467.                 top - 3 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING,
  4468.                 top - 2 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING, "128 facets");
  4469.     AddRadioButton(radio, button);
  4470.  
  4471.     button = NewRadioButton((left + right) / 2, right - MINORBORDER,
  4472.                 top - CHECKBOXHEIGHT, top, "512 facets");
  4473.     AddRadioButton(radio, button);
  4474.  
  4475.     button = NewRadioButton((left + right) / 2, right - MINORBORDER,
  4476.                 top - 2 * CHECKBOXHEIGHT - CHECKBOXSPACING,
  4477.                 top - CHECKBOXHEIGHT - CHECKBOXSPACING, "2048 facets");
  4478.     AddRadioButton(radio, button);
  4479.  
  4480.     button = NewRadioButton((left + right) / 2, right - MINORBORDER,
  4481.                 top - 3 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING,
  4482.                 top - 2 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING, "8192 facets");
  4483.     AddRadioButton(radio, button);
  4484.  
  4485.     var = GetIntVar("AddGeometryControls", geometry, SPHERESUBDIV);
  4486.     if (!var)
  4487.     {
  4488.     SetVar(geometry, SPHERESUBDIV, NewInt(2));
  4489.     }
  4490.  
  4491.     AssocDirectControlWithVar(radio, geometry, SPHERESUBDIV);
  4492.     SetVar(radio, HELPSTRING, NewString("This controls how many facets are used \
  4493. to approximate each sphere in the geometry object.  Higher numbers provide more \
  4494. realistic results, especially with specular reflection.  Lower numbers \
  4495. result in pictures which can be drawn much more quickly."));
  4496.  
  4497.     top = bottom - CHECKBOXSPACING;
  4498.  
  4499.     /*Make cylinder controls*/
  4500.     right = PICSPHEREBOXWID + left;
  4501.     bottom = top - TITLEBOXTOP - 3 * MINORBORDER - 3 * CHECKBOXSPACING - 5 * CHECKBOXHEIGHT;
  4502.     titleBox = NewTitleBox(left, right,
  4503.         bottom, top,
  4504.         "Cylinders and Frusta");
  4505.     PrefixList(panelContents, titleBox);
  4506.     SetVar(titleBox, PARENT, panelContents);
  4507.  
  4508.     /*Make the cylinder radio button group*/
  4509.     radio = NewRadioButtonGroup("Cylinder Facet Group");
  4510.     PrefixList(panelContents, radio);
  4511.     SetVar(radio, PARENT, panelContents);
  4512.     top -= TITLEBOXTOP + MINORBORDER;
  4513.  
  4514.     /*Make the buttons*/
  4515.     button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
  4516.                 top - CHECKBOXHEIGHT, top, "4 facets");
  4517.     AddRadioButton(radio, button);
  4518.  
  4519.     button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
  4520.                 top - 2 * CHECKBOXHEIGHT - CHECKBOXSPACING,
  4521.                 top - CHECKBOXHEIGHT - CHECKBOXSPACING, "8 facets");
  4522.     AddRadioButton(radio, button);
  4523.  
  4524.     button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
  4525.                 top - 3 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING,
  4526.                 top - 2 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING, "16 facets");
  4527.     AddRadioButton(radio, button);
  4528.  
  4529.     button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
  4530.                 top - 4 * CHECKBOXHEIGHT - 3 * CHECKBOXSPACING,
  4531.                 top - 3 * CHECKBOXHEIGHT - 3 * CHECKBOXSPACING, "32 facets");
  4532.     AddRadioButton(radio, button);
  4533.  
  4534.     button = NewRadioButton((left + right) / 2, right - MINORBORDER,
  4535.                 top - CHECKBOXHEIGHT, top, "64 facets");
  4536.     AddRadioButton(radio, button);
  4537.  
  4538.     button = NewRadioButton((left + right) / 2, right - MINORBORDER,
  4539.                 top - 2 * CHECKBOXHEIGHT - CHECKBOXSPACING,
  4540.                 top - CHECKBOXHEIGHT - CHECKBOXSPACING, "128 facets");
  4541.     AddRadioButton(radio, button);
  4542.  
  4543.     button = NewRadioButton((left + right) / 2, right - MINORBORDER,
  4544.                 top - 3 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING,
  4545.                 top - 2 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING, "256 facets");
  4546.     AddRadioButton(radio, button);
  4547.  
  4548.     button = NewRadioButton((left + right) / 2, right - MINORBORDER,
  4549.                 top - 4 * CHECKBOXHEIGHT - 3 * CHECKBOXSPACING,
  4550.                 top - 3 * CHECKBOXHEIGHT - 3 * CHECKBOXSPACING, "512 facets");
  4551.     AddRadioButton(radio, button);
  4552.  
  4553.     var = GetIntVar("AddGeometryControls", geometry, FRUSTUMSUBDIV);
  4554.     if (!var)
  4555.     {
  4556.     SetVar(geometry, FRUSTUMSUBDIV, NewInt(2));
  4557.     }
  4558.  
  4559.     AssocDirectControlWithVar(radio, geometry, FRUSTUMSUBDIV);
  4560.     SetVar(radio, HELPSTRING, NewString("This controls how many facets are used \
  4561. to approximate each cylinder in the geometry object.  Higher numbers provide more \
  4562. realistic results, especially with specular reflection.  Lower numbers \
  4563. result in pictures which can be drawn much more quickly."));
  4564.  
  4565.     /*Now the end caps button*/
  4566.     button = NewCheckBox(left + MINORBORDER, right - MINORBORDER,
  4567.                 top - 5 * CHECKBOXHEIGHT - 3 * CHECKBOXSPACING - MINORBORDER,
  4568.                 top - 4 * CHECKBOXHEIGHT - 3 * CHECKBOXSPACING - MINORBORDER,
  4569.                 "Show end caps", GetPredicate(geometry, CAPENDSP));
  4570.     SetVar(button, PARENT, panelContents);
  4571.     PrefixList(panelContents, button);
  4572.     if (!GetVar(geometry, CAPENDSP)) SetVar(geometry, CAPENDSP, NewInt(1));
  4573.     AssocDirectControlWithVar(button, geometry, CAPENDSP);
  4574.     SetVar(button, HELPSTRING, NewString("This controls whether end caps \
  4575. are drawn on the cylinders in this geomtry object.  If it is checked, \
  4576. end caps are drawn, and the cylinders appear as solid rods.  If it is not \
  4577. checked, the cylinders appear as hollow tubes."));
  4578.  
  4579.     return ObjTrue;
  4580. }
  4581.  
  4582. #ifdef PROTO
  4583. void ScaleAroundPoint(real sx, real sy, real sz, real px, real py, real pz)
  4584. #else
  4585. void ScaleAroundPoint(sx, sy, sz, px, py, pz)
  4586. real sx; real sy; real sz; real px; real py; real pz;
  4587. #endif
  4588. /*Scales subsequent drawing around a point*/
  4589. {
  4590. #ifdef GRAPHICS
  4591.     Matrix m;
  4592.  
  4593.     PushTransformation();
  4594.     loadmatrix(Identity);
  4595.     translate(px, py, pz);
  4596.     getmatrix(m);
  4597.     PopTransformation();
  4598.     multmatrix(m);
  4599.  
  4600.     PushTransformation();
  4601.     loadmatrix(Identity);
  4602.     scale(sx, sy, sz);
  4603.     getmatrix(m);
  4604.     PopTransformation();
  4605.     multmatrix(m);
  4606.  
  4607.     PushTransformation();
  4608.     loadmatrix(Identity);
  4609.     translate(-px, -py, -pz);
  4610.     getmatrix(m);
  4611.     PopTransformation();
  4612.     multmatrix(m);
  4613. #endif
  4614. }
  4615.  
  4616. #ifdef PROTO
  4617. void DrawPanelLines(real x1, real y1, real z1,
  4618.             real x2, real y2, real z2,
  4619.             char axis, real min, real max, real step)
  4620. #else
  4621. void DrawPanelLines( x1,  y1,  z1,
  4622.              x2,  y2,  z2,
  4623.              axis,  min,  max,  step)
  4624. real x1, y1, z1;
  4625. real x2, y2, z2;
  4626. char axis;
  4627. real min, max, step;
  4628. #endif
  4629. /*Draws a bunch of lines from min to max by step along axis (x, y, z)
  4630.   using [xyz]1 and [xyz]2 as a basis.*/
  4631. {
  4632.     real cur;
  4633.  
  4634.     if (min > max) {cur = max; max = min; min = cur;}
  4635.  
  4636.     cur = rceil(min / step) * step;
  4637.  
  4638.     while (cur <= max)
  4639.     {
  4640.     if (cur >= min)
  4641.     {
  4642.         switch(axis)
  4643.         {
  4644.         case 'x':
  4645.             x1 = x2 = cur;
  4646.             break;
  4647.         case 'y':
  4648.             y1 = y2 = cur;
  4649.             break;
  4650.         case 'z':
  4651.             z1 = z2 = cur;
  4652.             break;
  4653.         }
  4654.         DrawSpaceLine(x1, y1, z1, x2, y2, z2);
  4655.     }
  4656.  
  4657.     cur += step;
  4658.     }
  4659. }
  4660.  
  4661. #ifdef PROTO
  4662. void DrawVisObject(ObjPtr object)
  4663. #else
  4664. void DrawVisObject(object)
  4665. ObjPtr object;
  4666. #endif
  4667. /*Draws a visualization object*/
  4668. {
  4669.     ObjPtr var;
  4670.     float xScale, yScale, zScale;
  4671.     real bounds[6];
  4672.     int panelFlags, shadowFlags, mirrorFlags;
  4673.     int oldMinDrawingQuality;
  4674.     Bool drawBackground;
  4675.     Bool antiAlias = false;    /*True iff antialiased lines*/
  4676.  
  4677.     drawBackground = GetPredicate(object, DRAWBACKGROUND);
  4678.  
  4679.     /*Get bounds*/
  4680.     GetBounds(object, bounds);
  4681.  
  4682.     /*Get x, y, z, scale*/
  4683.     var = GetVar(object, XSCALE);
  4684.     if (var)
  4685.     {
  4686.     xScale = GetReal(var);
  4687.     }
  4688.     else 
  4689.     {
  4690.     xScale = 1.0;
  4691.     }
  4692.     var = GetVar(object, YSCALE);
  4693.     if (var)
  4694.     {
  4695.     yScale = GetReal(var);
  4696.     }
  4697.     else 
  4698.     {
  4699.     yScale = 1.0;
  4700.     }
  4701.     var = GetVar(object, ZSCALE);
  4702.     if (var)
  4703.     {
  4704.     zScale = GetReal(var);
  4705.     }
  4706.     else 
  4707.     {
  4708.     zScale = 1.0;
  4709.     }
  4710.  
  4711.     PushTransformation();
  4712.  
  4713.     orderReversed = false;
  4714.  
  4715.     /*Scale the object*/
  4716.     ScaleAroundPoint(xScale, yScale, zScale, bounds[0], bounds[2], bounds[4]);
  4717.     if (xScale < 0.0) orderReversed = orderReversed ? false : true;
  4718.     if (yScale < 0.0) orderReversed = orderReversed ? false : true;
  4719.     if (zScale < 0.0) orderReversed = orderReversed ? false : true;
  4720.  
  4721.     /*Draw the main object*/
  4722.     DrawObject(object);
  4723.  
  4724.     oldMinDrawingQuality = minDrawingQuality;
  4725.     minDrawingQuality = DQ_WALLS + 1;
  4726.  
  4727.     /*Scale bounds*/
  4728.     bounds[1] = bounds[0] + (bounds[1] - bounds[0]) * xScale;
  4729.     bounds[3] = bounds[2] + (bounds[3] - bounds[2]) * xScale;
  4730.     bounds[5] = bounds[4] + (bounds[5] - bounds[4]) * xScale;
  4731.  
  4732.     /*Draw the panels, if appropriate*/
  4733.     var = GetVar(object, WALLPANELFLAGS);
  4734.     if (var && maxDrawingQuality >= DQ_WALLS && !drawingTransparent)
  4735.     {
  4736.     panelFlags = GetInt(var);
  4737.     }
  4738.     else
  4739.     {
  4740.     panelFlags = 0;
  4741.     }
  4742.  
  4743.     /*See if there are any mirrors*/
  4744.     var = GetVar(object, WALLMIRRORFLAGS);
  4745.     if (var && maxDrawingQuality >= DQ_WALLS)
  4746.     {
  4747.     mirrorFlags = GetInt(var);
  4748.     }
  4749.     else
  4750.     {
  4751.     mirrorFlags = 0;
  4752.     }
  4753.  
  4754.     /*See if there are any shadows*/
  4755.     var = GetVar(object, WALLSHADOWFLAGS);
  4756.     if (var && maxDrawingQuality >= DQ_WALLS && !drawingTransparent)
  4757.     {
  4758.     shadowFlags = GetInt(var);
  4759.     }
  4760.     else
  4761.     {
  4762.     shadowFlags = 0;
  4763.     }
  4764.  
  4765.     /*Draw reflections through mirrors*/
  4766.     if (mirrorFlags)
  4767.     {
  4768.     /*First order reflections*/
  4769.     orderReversed = orderReversed ? false : true;
  4770.     if (mirrorFlags & 1)    /*-X*/
  4771.     {
  4772.         PushTransformation();
  4773.         ScaleAroundPoint(-1.0, 1.0, 1.0, bounds[0], bounds[2], bounds[4]);
  4774.         DrawObject(object);
  4775.         PopTransformation();
  4776.     }
  4777.     if (mirrorFlags & 2)    /*+X*/
  4778.     {
  4779.         PushTransformation();
  4780.         ScaleAroundPoint(-1.0, 1.0, 1.0, bounds[1], bounds[3], bounds[5]);
  4781.         DrawObject(object);
  4782.         PopTransformation();
  4783.     }
  4784.     if (mirrorFlags & 4)    /*-Y*/
  4785.     {
  4786.         PushTransformation();
  4787.         ScaleAroundPoint(1.0, -1.0, 1.0, bounds[0], bounds[2], bounds[4]);
  4788.         DrawObject(object);
  4789.         PopTransformation();
  4790.     }
  4791.     if (mirrorFlags & 8)    /*+Y*/
  4792.     {
  4793.         PushTransformation();
  4794.         ScaleAroundPoint(1.0, -1.0, 1.0, bounds[1], bounds[3], bounds[5]);
  4795.         DrawObject(object);
  4796.         PopTransformation();
  4797.     }
  4798.     if (mirrorFlags & 16)    /*-Z*/
  4799.     {
  4800.         PushTransformation();
  4801.         ScaleAroundPoint(1.0, 1.0, -1.0, bounds[0], bounds[2], bounds[4]);
  4802.         DrawObject(object);
  4803.         PopTransformation();
  4804.     }
  4805.     if (mirrorFlags & 32)    /*+Z*/
  4806.     {
  4807.         PushTransformation();
  4808.         ScaleAroundPoint(1.0, 1.0, -1.0, bounds[1], bounds[3], bounds[5]);
  4809.         DrawObject(object);
  4810.         PopTransformation();
  4811.     }
  4812.  
  4813.     /*Second order reflections*/
  4814.     orderReversed = orderReversed ? false : true;
  4815.     if ((mirrorFlags & 1) && (mirrorFlags & 4))        /* -X, -Y */
  4816.     {
  4817.         PushTransformation();
  4818.         ScaleAroundPoint(-1.0, -1.0, 1.0, bounds[0], bounds[2], bounds[4]);
  4819.         DrawObject(object);
  4820.         PopTransformation();
  4821.     }
  4822.     if ((mirrorFlags & 1) && (mirrorFlags & 8))        /* -X, +Y */
  4823.     {
  4824.         PushTransformation();
  4825.         ScaleAroundPoint(-1.0, -1.0, 1.0, bounds[0], bounds[3], bounds[4]);
  4826.         DrawObject(object);
  4827.         PopTransformation();
  4828.     }
  4829.     if ((mirrorFlags & 2) && (mirrorFlags & 4))        /* +X, -Y */
  4830.     {
  4831.         PushTransformation();
  4832.         ScaleAroundPoint(-1.0, -1.0, 1.0, bounds[1], bounds[2], bounds[4]);
  4833.         DrawObject(object);
  4834.         PopTransformation();
  4835.     }
  4836.     if ((mirrorFlags & 2) && (mirrorFlags & 8))        /* +X, +Y */
  4837.     {
  4838.         PushTransformation();
  4839.         ScaleAroundPoint(-1.0, -1.0, 1.0, bounds[1], bounds[3], bounds[4]);
  4840.         DrawObject(object);
  4841.         PopTransformation();
  4842.     }
  4843.     if ((mirrorFlags & 1) && (mirrorFlags & 16))    /* -X, -Z */
  4844.     {
  4845.         PushTransformation();
  4846.         ScaleAroundPoint(-1.0, 1.0, -1.0, bounds[0], bounds[2], bounds[4]);
  4847.         DrawObject(object);
  4848.         PopTransformation();
  4849.     }
  4850.     if ((mirrorFlags & 1) && (mirrorFlags & 32))    /* -X, +Z */
  4851.     {
  4852.         PushTransformation();
  4853.         ScaleAroundPoint(-1.0, 1.0, -1.0, bounds[0], bounds[3], bounds[5]);
  4854.         DrawObject(object);
  4855.         PopTransformation();
  4856.     }
  4857.     if ((mirrorFlags & 2) && (mirrorFlags & 16))    /* +X, -Z */
  4858.     {
  4859.         PushTransformation();
  4860.         ScaleAroundPoint(-1.0, 1.0, -1.0, bounds[1], bounds[2], bounds[4]);
  4861.         DrawObject(object);
  4862.         PopTransformation();
  4863.     }
  4864.     if ((mirrorFlags & 2) && (mirrorFlags & 32))    /* +X, +Z */
  4865.     {
  4866.         PushTransformation();
  4867.         ScaleAroundPoint(-1.0, 1.0, -1.0, bounds[1], bounds[3], bounds[5]);
  4868.         DrawObject(object);
  4869.         PopTransformation();
  4870.     }
  4871.     if ((mirrorFlags & 4) && (mirrorFlags & 16))    /* -Y, -Z */
  4872.     {
  4873.         PushTransformation();
  4874.         ScaleAroundPoint(1.0, -1.0, -1.0, bounds[0], bounds[2], bounds[4]);
  4875.         DrawObject(object);
  4876.         PopTransformation();
  4877.     }
  4878.     if ((mirrorFlags & 4) && (mirrorFlags & 32))    /* -Y, +Z */
  4879.     {
  4880.         PushTransformation();
  4881.         ScaleAroundPoint(1.0, -1.0, -1.0, bounds[0], bounds[2], bounds[5]);
  4882.         DrawObject(object);
  4883.         PopTransformation();
  4884.     }
  4885.     if ((mirrorFlags & 8) && (mirrorFlags & 16))    /* +Y, -Z */
  4886.     {
  4887.         PushTransformation();
  4888.         ScaleAroundPoint(1.0, -1.0, -1.0, bounds[1], bounds[3], bounds[4]);
  4889.         DrawObject(object);
  4890.         PopTransformation();
  4891.     }
  4892.     if ((mirrorFlags & 8) && (mirrorFlags & 32))    /* +Y, +Z */
  4893.     {
  4894.         PushTransformation();
  4895.         ScaleAroundPoint(1.0, -1.0, -1.0, bounds[1], bounds[3], bounds[5]);
  4896.         DrawObject(object);
  4897.         PopTransformation();
  4898.     }
  4899.  
  4900.     /*Third order reflections*/
  4901.     orderReversed = orderReversed ? false : true;
  4902.     if ((mirrorFlags & 1) && (mirrorFlags & 4) && (mirrorFlags & 16))    /* -X, -Y, -Z */
  4903.     {
  4904.         PushTransformation();
  4905.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[0], bounds[2], bounds[4]);
  4906.         DrawObject(object);
  4907.         PopTransformation();
  4908.     }
  4909.     if ((mirrorFlags & 1) && (mirrorFlags & 4) && (mirrorFlags & 32))    /* -X, -Y, +Z */
  4910.     {
  4911.         PushTransformation();
  4912.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[0], bounds[2], bounds[5]);
  4913.         DrawObject(object);
  4914.         PopTransformation();
  4915.     }
  4916.     if ((mirrorFlags & 1) && (mirrorFlags & 4) && (mirrorFlags & 16))    /* -X, +Y, -Z */
  4917.     {
  4918.         PushTransformation();
  4919.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[0], bounds[3], bounds[4]);
  4920.         DrawObject(object);
  4921.         PopTransformation();
  4922.     }
  4923.     if ((mirrorFlags & 1) && (mirrorFlags & 4) && (mirrorFlags & 32))    /* -X, +Y, +Z */
  4924.     {
  4925.         PushTransformation();
  4926.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[0], bounds[3], bounds[5]);
  4927.         DrawObject(object);
  4928.         PopTransformation();
  4929.     }
  4930.     if ((mirrorFlags & 2) && (mirrorFlags & 4) && (mirrorFlags & 16))    /* +X, -Y, -Z */
  4931.     {
  4932.         PushTransformation();
  4933.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[1], bounds[2], bounds[4]);
  4934.         DrawObject(object);
  4935.         PopTransformation();
  4936.     }
  4937.     if ((mirrorFlags & 2) && (mirrorFlags & 4) && (mirrorFlags & 32))    /* +X, -Y, +Z */
  4938.     {
  4939.         PushTransformation();
  4940.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[1], bounds[2], bounds[5]);
  4941.         DrawObject(object);
  4942.         PopTransformation();
  4943.     }
  4944.     if ((mirrorFlags & 2) && (mirrorFlags & 4) && (mirrorFlags & 16))    /* +X, +Y, -Z */
  4945.     {
  4946.         PushTransformation();
  4947.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[1], bounds[3], bounds[4]);
  4948.         DrawObject(object);
  4949.         PopTransformation();
  4950.     }
  4951.     if ((mirrorFlags & 2) && (mirrorFlags & 4) && (mirrorFlags & 32))    /* +X, +Y, +Z */
  4952.     {
  4953.         PushTransformation();
  4954.         ScaleAroundPoint(-1.0, -1.0, -1.0, bounds[1], bounds[3], bounds[5]);
  4955.         DrawObject(object);
  4956.         PopTransformation();
  4957.     }
  4958.  
  4959.     /*Back to original order*/
  4960.     orderReversed = orderReversed ? false : true;
  4961.     }
  4962.  
  4963.     /*Draw the panels with no Z-buffering*/
  4964.     if (panelFlags && drawBackground)
  4965.     {
  4966.     int matIndex;
  4967.  
  4968.     BeginMask(true, true, true, false);
  4969.  
  4970.     backface(TRUE);
  4971.  
  4972.     if (rgbp)
  4973.     {
  4974.         real *elements;
  4975.         var = GetVar(object, WALLPANELCOLOR);
  4976.         if (var)
  4977.         {
  4978.         elements = ELEMENTS(var);
  4979.         }
  4980.         else
  4981.         {
  4982.         elements = 0;
  4983.         }
  4984.  
  4985.         matIndex = 0;
  4986.         material[matIndex++] = DIFFUSE;
  4987.         material[matIndex++] = elements ? elements[0] : 0.5;
  4988.         material[matIndex++] = elements ? elements[1] : 0.5;
  4989.         material[matIndex++] = elements ? elements[2] : 0.5;
  4990.         material[matIndex++] = LMNULL;
  4991.         lmdef(DEFMATERIAL, VISMATERIAL, matIndex, material);
  4992.         lmbind(MATERIAL, VISMATERIAL);
  4993.         lmcolor(LMC_DIFFUSE);
  4994.     }
  4995.  
  4996.     if (hasDithering)
  4997.     {
  4998. #ifdef DT_ON
  4999.         dither(DT_ON);
  5000. #endif
  5001.     }
  5002.  
  5003.     if (!rgbp) SetUIColor(UIGRAY12);
  5004.  
  5005.     if (panelFlags & 1)
  5006.     {
  5007.         /*-x*/
  5008.         FillSpaceRect(
  5009.         bounds[0], bounds[3], bounds[4],
  5010.         bounds[0], bounds[3], bounds[5],
  5011.         bounds[0], bounds[2], bounds[5],
  5012.         bounds[0], bounds[2], bounds[4],
  5013.         rgbp ? 1.0 : 0.0, 0.0, 0.0);
  5014.     }
  5015.     if (panelFlags & 2)
  5016.     {
  5017.         /*+x*/
  5018.         FillSpaceRect(
  5019.         bounds[1], bounds[2], bounds[4],
  5020.         bounds[1], bounds[2], bounds[5],
  5021.         bounds[1], bounds[3], bounds[5],
  5022.         bounds[1], bounds[3], bounds[4],
  5023.         rgbp ? -1.0 : 0.0, 0.0, 0.0);
  5024.     }
  5025.  
  5026.     if (!rgbp) SetUIColor(UIGRAY25);
  5027.  
  5028.     if (panelFlags & 4)
  5029.     {
  5030.         /*-y*/
  5031.         FillSpaceRect(
  5032.         bounds[1], bounds[2], bounds[4],
  5033.         bounds[0], bounds[2], bounds[4],
  5034.         bounds[0], bounds[2], bounds[5],
  5035.         bounds[1], bounds[2], bounds[5],
  5036.         0.0, rgbp ? 1.0 : 0.0, 0.0);
  5037.     }
  5038.     if (panelFlags & 8)
  5039.     {
  5040.         /*+y*/
  5041.         FillSpaceRect(
  5042.         bounds[1], bounds[3], bounds[4],
  5043.         bounds[1], bounds[3], bounds[5],
  5044.         bounds[0], bounds[3], bounds[5],
  5045.         bounds[0], bounds[3], bounds[4],
  5046.         0.0, rgbp ? -1.0 : 0.0, 0.0);
  5047.     }
  5048.  
  5049.     if (!rgbp) SetUIColor(UIGRAY25);
  5050.  
  5051.     if (panelFlags & 16)
  5052.     {
  5053.         /*floor*/
  5054.         FillSpaceRect(
  5055.         bounds[0], bounds[2], bounds[4],
  5056.         bounds[1], bounds[2], bounds[4],
  5057.         bounds[1], bounds[3], bounds[4],
  5058.         bounds[0], bounds[3], bounds[4],
  5059.         0.0, 0.0, rgbp ? 1.0 : 0.0);
  5060.     }
  5061.     if (panelFlags & 32)
  5062.     {
  5063.         /*ceiling*/
  5064.         FillSpaceRect(
  5065.         bounds[0], bounds[2], bounds[5],
  5066.         bounds[0], bounds[3], bounds[5],
  5067.         bounds[1], bounds[3], bounds[5],
  5068.         bounds[1], bounds[2], bounds[5],
  5069.         0.0, 0.0, rgbp ? -1.0 : 0.0);
  5070.     }
  5071.  
  5072.     if (hasDithering)
  5073.     {
  5074. #ifdef DT_OFF
  5075.         dither(DT_OFF);
  5076. #endif
  5077.     }
  5078.  
  5079.     if (rgbp)
  5080.     {
  5081.         lmcolor(LMC_COLOR);
  5082.     }
  5083.  
  5084.     backface(FALSE);
  5085.  
  5086.     EndMask();
  5087.     }
  5088.  
  5089.  
  5090.     /*Draw shadows on panels*/
  5091.     if (shadowFlags)
  5092.     {
  5093.     drawSolid = true;
  5094.     SetUIColor(UIBLACK);
  5095.     OverrideColor(true);
  5096.  
  5097.     if ((shadowFlags & 1) && (observerPosition[0] > bounds[0]))    /*-X*/
  5098.     {
  5099.         if ((panelFlags & 1) && drawBackground)
  5100.         {
  5101.         BeginMask(true, true, true, false);
  5102.         }
  5103.         PushTransformation();
  5104.         ScaleAroundPoint(0.0001, 1.0, 1.0, bounds[0], bounds[2], bounds[4]);
  5105.         DrawObject(object);
  5106.         PopTransformation();
  5107.         if (panelFlags & 1)
  5108.         {
  5109.         EndMask();
  5110.         }
  5111.     }
  5112.     if ((shadowFlags & 2) && (observerPosition[0] < bounds[1]))    /*+X*/
  5113.     {
  5114.         if (panelFlags & 2)
  5115.         {
  5116.         BeginMask(true, true, true, false);
  5117.         }
  5118.         PushTransformation();
  5119.         ScaleAroundPoint(0.0001, 1.0, 1.0, bounds[1], bounds[3], bounds[5]);
  5120.         DrawObject(object);
  5121.         PopTransformation();
  5122.         if (panelFlags & 1)
  5123.         {
  5124.         EndMask();
  5125.         }
  5126.     }
  5127.     if ((shadowFlags & 4) && (observerPosition[1] > bounds[2]))    /*-Y*/
  5128.     {
  5129.         if (panelFlags & 4)
  5130.         {
  5131.         BeginMask(true, true, true, false);
  5132.         }
  5133.         PushTransformation();
  5134.         ScaleAroundPoint(1.0, 0.0001, 1.0, bounds[0], bounds[2], bounds[4]);
  5135.         DrawObject(object);
  5136.         PopTransformation();
  5137.         if (panelFlags & 1)
  5138.         {
  5139.         EndMask();
  5140.         }
  5141.     }
  5142.     if ((shadowFlags & 8) && (observerPosition[1] < bounds[3]))    /*+Y*/
  5143.     {
  5144.         if (panelFlags & 8)
  5145.         {
  5146.         BeginMask(true, true, true, false);
  5147.         }
  5148.         PushTransformation();
  5149.         ScaleAroundPoint(1.0, 0.0001, 1.0, bounds[1], bounds[3], bounds[5]);
  5150.         DrawObject(object);
  5151.         PopTransformation();
  5152.         if (panelFlags & 1)
  5153.         {
  5154.         EndMask();
  5155.         }
  5156.     }
  5157.     if ((shadowFlags & 16) && (observerPosition[2] > bounds[4]))    /*-Z*/
  5158.     {
  5159.         if (panelFlags & 16)
  5160.         {
  5161.         BeginMask(true, true, true, false);
  5162.         }
  5163.         PushTransformation();
  5164.         ScaleAroundPoint(1.0, 1.0, 0.0001, bounds[0], bounds[2], bounds[4]);
  5165.         DrawObject(object);
  5166.         PopTransformation();
  5167.         if (panelFlags & 1)
  5168.         {
  5169.         EndMask();
  5170.         }
  5171.     }
  5172.     if ((shadowFlags & 32) && (observerPosition[2] < bounds[5]))    /*+Z*/
  5173.     {
  5174.         if (panelFlags & 32)
  5175.         {
  5176.         BeginMask(true, true, true, false);
  5177.         }
  5178.         PushTransformation();
  5179.         ScaleAroundPoint(1.0, 1.0, 0.0001, bounds[1], bounds[3], bounds[5]);
  5180.         DrawObject(object);
  5181.         PopTransformation();
  5182.         if (panelFlags & 1)
  5183.         {
  5184.         EndMask();
  5185.         }
  5186.     }
  5187.     OverrideColor(false);
  5188.     drawSolid = false;
  5189.     }
  5190.  
  5191.     /*Draw lines over shadow*/
  5192.     if (panelFlags)
  5193.     {
  5194.     var = GetVar(object, LINEWIDTH);
  5195.     if (var)
  5196.     {
  5197.         int width;
  5198.         width = GetReal(var);
  5199.         if (width < 1) width = 1;
  5200.         SetLineWidth(width);
  5201.     }
  5202.  
  5203.     if (hasAntialiasedLines && rgbp && GetPredicate(object, ANTIALIASLINES))
  5204.     {
  5205.         linesmooth(SML_ON);
  5206.         blendfunction(BF_SA, BF_MSA);
  5207.         subpixel(TRUE);
  5208.         antiAlias = true;
  5209.     }
  5210.  
  5211.     if (GetPredicate(object, DRAWOUTLINE))
  5212.     {
  5213.         /*Draw the outline*/
  5214.  
  5215.         var = GetVar(object, WALLLINESCOLOR);
  5216.         if (var)
  5217.         {
  5218.         SetObjectColor(var);
  5219.         }
  5220.         else
  5221.         {
  5222.         SetUIColor(UIGRAY75);
  5223.         }
  5224.  
  5225.         if (panelFlags & 1)
  5226.         {
  5227.         /*-x*/
  5228.         FrameSpaceRect(
  5229.             bounds[0], bounds[3], bounds[4],
  5230.             bounds[0], bounds[3], bounds[5],
  5231.             bounds[0], bounds[2], bounds[5],
  5232.             bounds[0], bounds[2], bounds[4]);
  5233.         }
  5234.         if (panelFlags & 2)
  5235.         {
  5236.         /*+x*/
  5237.         FrameSpaceRect(
  5238.             bounds[1], bounds[2], bounds[4],
  5239.             bounds[1], bounds[2], bounds[5],
  5240.             bounds[1], bounds[3], bounds[5],
  5241.             bounds[1], bounds[3], bounds[4]);
  5242.         }
  5243.  
  5244.         if (!rgbp) SetUIColor(UIGRAY25);
  5245.  
  5246.         if (panelFlags & 4)
  5247.         {
  5248.         /*-y*/
  5249.         FrameSpaceRect(
  5250.             bounds[1], bounds[2], bounds[4],
  5251.             bounds[0], bounds[2], bounds[4],
  5252.             bounds[0], bounds[2], bounds[5],
  5253.             bounds[1], bounds[2], bounds[5]);
  5254.         }
  5255.         if (panelFlags & 8)
  5256.         {
  5257.         /*+y*/
  5258.         FrameSpaceRect(
  5259.             bounds[1], bounds[3], bounds[4],
  5260.             bounds[1], bounds[3], bounds[5],
  5261.             bounds[0], bounds[3], bounds[5],
  5262.             bounds[0], bounds[3], bounds[4]);
  5263.         }
  5264.  
  5265.         if (!rgbp) SetUIColor(UIGRAY25);
  5266.  
  5267.         if (panelFlags & 16)
  5268.         {
  5269.         /*floor*/
  5270.         FrameSpaceRect(
  5271.             bounds[0], bounds[2], bounds[4],
  5272.             bounds[1], bounds[2], bounds[4],
  5273.             bounds[1], bounds[3], bounds[4],
  5274.             bounds[0], bounds[3], bounds[4]);
  5275.         }
  5276.         if (panelFlags & 32)
  5277.         {
  5278.         /*ceiling*/
  5279.         FrameSpaceRect(
  5280.             bounds[0], bounds[2], bounds[5],
  5281.             bounds[0], bounds[3], bounds[5],
  5282.             bounds[1], bounds[3], bounds[5],
  5283.             bounds[1], bounds[2], bounds[5]);
  5284.         }
  5285.     }
  5286.  
  5287.     if (GetPredicate(object, DRAWGRID))
  5288.     {
  5289.         /*Draw the grid*/
  5290.         double xSpace, ySpace, zSpace;
  5291.         real majorStep[3];
  5292.         real maxSize;
  5293.         int nTics;
  5294.  
  5295.         MakeVar(object, AXISMAJORSTEP);
  5296.         var = GetFixedArrayVar("DrawVisObject", object, AXISMAJORSTEP, 1, 3L);
  5297.         if (var)
  5298.         {
  5299.         Array2CArray(majorStep, var);
  5300.         }
  5301.         else
  5302.         {
  5303.         majorStep[0] = majorStep[1] = majorStep[2] = 1.0;
  5304.         }
  5305.  
  5306.         /*Do the x, y, and z axes*/
  5307.         xSpace = majorStep[0];
  5308.         ySpace = majorStep[1];
  5309.         zSpace = majorStep[2];
  5310.  
  5311.         var = GetVar(object, WALLLINESCOLOR);
  5312.         if (var)
  5313.         {
  5314.         SetObjectColor(var);
  5315.         }
  5316.         else
  5317.         {
  5318.         SetUIColor(UIGRAY75);
  5319.         }
  5320.  
  5321.         if (panelFlags & 1)
  5322.         {
  5323.         /*-x*/
  5324.         DrawPanelLines(
  5325.             bounds[0], bounds[2], bounds[4],
  5326.             bounds[0], bounds[3], bounds[4],
  5327.             'z', bounds[4], bounds[5], zSpace);
  5328.         DrawPanelLines(
  5329.             bounds[0], bounds[2], bounds[4],
  5330.             bounds[0], bounds[2], bounds[5],
  5331.             'y', bounds[2], bounds[3], ySpace);
  5332.         }
  5333.  
  5334.         if (panelFlags & 2)
  5335.         {
  5336.         /*+x*/
  5337.         DrawPanelLines(
  5338.             bounds[1], bounds[2], bounds[4],
  5339.             bounds[1], bounds[3], bounds[4],
  5340.             'z', bounds[4], bounds[5], zSpace);
  5341.         DrawPanelLines(
  5342.             bounds[1], bounds[2], bounds[4],
  5343.             bounds[1], bounds[2], bounds[5],
  5344.             'y', bounds[2], bounds[3], ySpace);
  5345.         }
  5346.  
  5347.         if (panelFlags & 4)
  5348.         {
  5349.         /*-y*/
  5350.         DrawPanelLines(
  5351.             bounds[0], bounds[2], bounds[4],
  5352.             bounds[1], bounds[2], bounds[4],
  5353.             'z', bounds[4], bounds[5], zSpace);
  5354.         DrawPanelLines(
  5355.             bounds[0], bounds[2], bounds[4],
  5356.             bounds[0], bounds[2], bounds[5],
  5357.             'x', bounds[0], bounds[1], ySpace);
  5358.         }
  5359.         if (panelFlags & 8)
  5360.         {
  5361.         /*+y*/
  5362.         DrawPanelLines(
  5363.             bounds[0], bounds[3], bounds[4],
  5364.             bounds[1], bounds[3], bounds[4],
  5365.             'z', bounds[4], bounds[5], zSpace);
  5366.         DrawPanelLines(
  5367.             bounds[0], bounds[3], bounds[4],
  5368.             bounds[0], bounds[3], bounds[5],
  5369.             'x', bounds[0], bounds[1], ySpace);
  5370.         }
  5371.  
  5372.         if (!rgbp) SetUIColor(UIGRAY25);
  5373.  
  5374.         if (panelFlags & 16)
  5375.         {
  5376.         /*floor*/
  5377.         DrawPanelLines(
  5378.             bounds[0], bounds[2], bounds[4],
  5379.             bounds[0], bounds[3], bounds[4],
  5380.             'x', bounds[0], bounds[1], zSpace);
  5381.         DrawPanelLines(
  5382.             bounds[0], bounds[2], bounds[4],
  5383.             bounds[1], bounds[2], bounds[4],
  5384.             'y', bounds[2], bounds[3], ySpace);
  5385.         }
  5386.         if (panelFlags & 32)
  5387.         {
  5388.         /*ceiling*/
  5389.         DrawPanelLines(
  5390.             bounds[0], bounds[2], bounds[5],
  5391.             bounds[0], bounds[3], bounds[5],
  5392.             'x', bounds[0], bounds[1], zSpace);
  5393.         DrawPanelLines(
  5394.             bounds[0], bounds[2], bounds[5],
  5395.             bounds[1], bounds[2], bounds[5],
  5396.             'y', bounds[2], bounds[3], ySpace);
  5397.         }
  5398.     }
  5399.     SetLineWidth(1);
  5400.     if (antiAlias)
  5401.     {
  5402.         linesmooth(SML_OFF);
  5403.         blendfunction(BF_ONE, BF_ZERO);
  5404.         subpixel(FALSE);
  5405.     }
  5406.     }
  5407.  
  5408.     /*Draw the panels with only Z-buffering, no drawing*/
  5409.     if (panelFlags && drawBackground)
  5410.     {
  5411.     int matIndex;
  5412.  
  5413.     BeginMask(false, false, false, true);
  5414.  
  5415.     backface(TRUE);
  5416.     if (panelFlags & 1)
  5417.     {
  5418.         /*-x*/
  5419.         FillSpaceRect(
  5420.         bounds[0], bounds[3], bounds[4],
  5421.         bounds[0], bounds[3], bounds[5],
  5422.         bounds[0], bounds[2], bounds[5],
  5423.         bounds[0], bounds[2], bounds[4],
  5424.         rgbp ? 1.0 : 0.0, 0.0, 0.0);
  5425.     }
  5426.     if (panelFlags & 2)
  5427.     {
  5428.         /*+x*/
  5429.         FillSpaceRect(
  5430.         bounds[1], bounds[2], bounds[4],
  5431.         bounds[1], bounds[2], bounds[5],
  5432.         bounds[1], bounds[3], bounds[5],
  5433.         bounds[1], bounds[3], bounds[4],
  5434.         rgbp ? -1.0 : 0.0, 0.0, 0.0);
  5435.     }
  5436.     if (panelFlags & 4)
  5437.     {
  5438.         /*-y*/
  5439.         FillSpaceRect(
  5440.         bounds[1], bounds[2], bounds[4],
  5441.         bounds[0], bounds[2], bounds[4],
  5442.         bounds[0], bounds[2], bounds[5],
  5443.         bounds[1], bounds[2], bounds[5],
  5444.         0.0, rgbp ? 1.0 : 0.0, 0.0);
  5445.     }
  5446.     if (panelFlags & 8)
  5447.     {
  5448.         /*+y*/
  5449.         FillSpaceRect(
  5450.         bounds[1], bounds[3], bounds[4],
  5451.         bounds[1], bounds[3], bounds[5],
  5452.         bounds[0], bounds[3], bounds[5],
  5453.         bounds[0], bounds[3], bounds[4],
  5454.         0.0, rgbp ? -1.0 : 0.0, 0.0);
  5455.     }
  5456.     if (panelFlags & 16)
  5457.     {
  5458.         /*floor*/
  5459.         FillSpaceRect(
  5460.         bounds[0], bounds[2], bounds[4],
  5461.         bounds[1], bounds[2], bounds[4],
  5462.         bounds[1], bounds[3], bounds[4],
  5463.         bounds[0], bounds[3], bounds[4],
  5464.         0.0, 0.0, rgbp ? 1.0 : 0.0);
  5465.     }
  5466.     if (panelFlags & 32)
  5467.     {
  5468.         /*ceiling*/
  5469.         FillSpaceRect(
  5470.         bounds[0], bounds[2], bounds[5],
  5471.         bounds[0], bounds[3], bounds[5],
  5472.         bounds[1], bounds[3], bounds[5],
  5473.         bounds[1], bounds[2], bounds[5],
  5474.         0.0, 0.0, rgbp ? -1.0 : 0.0);
  5475.     }
  5476.  
  5477.     backface(FALSE);
  5478.  
  5479.     EndMask();
  5480.     }
  5481.  
  5482.     PopTransformation();
  5483.  
  5484.     minDrawingQuality = oldMinDrawingQuality;
  5485. }
  5486.  
  5487. static ObjPtr GeometryInit(object)
  5488. ObjPtr object;
  5489. /*Initializes a geometry object*/
  5490. {
  5491.     ObjPtr minMax;
  5492.     real bounds[6];
  5493.     real xySize, zSize;
  5494.     ObjPtr colorObj;
  5495.     ObjPtr normalsObj;
  5496.  
  5497.     colorObj = GetVar(object, REPOBJ);
  5498.     MakeVar(colorObj, CPALETTE);
  5499.     if (GetPredicate(colorObj, COLORBYSELF) && GetVar(colorObj, CPALETTE))
  5500.     {
  5501.     SetVar(object, COLOROBJ, colorObj);
  5502.     if (colorObj)
  5503.     {
  5504.         SetVar(object, COLORS, ObjTrue);
  5505.     }
  5506.     }
  5507.     SetVar(object, MAINDATASET, colorObj);
  5508.     if (normalsObj = GetVar(colorObj, NORMALSOBJ))
  5509.     {
  5510.     SetVar(object, NORMALSOBJ, normalsObj);
  5511.     }
  5512.  
  5513.     return ObjTrue;
  5514. }
  5515.  
  5516. static ObjPtr VisualizeVisObject(object)
  5517. ObjPtr object;
  5518. /*Visualizes a single vis object*/
  5519. {
  5520.     if (object)
  5521.     {
  5522.     IdleAllWindows();
  5523.     AddObjToSpace(object, FindSpace(selWinInfo), GetVar((ObjPtr) selWinInfo, CORRAL), NULLOBJ, NULLOBJ);
  5524.     return ObjTrue;
  5525.     }
  5526.     return ObjFalse;
  5527. }
  5528.  
  5529. ObjPtr DummyDeformed(object)
  5530. ObjPtr object;
  5531. /*Dummy deformed method DIK remove when deformation and scale work on everything.*/
  5532. {
  5533.     SetVar(object, PICDEFORMED, ObjTrue);
  5534.     return ObjTrue;
  5535. }
  5536.  
  5537. static ObjPtr MakeBoundedXName(object)
  5538. ObjPtr object;
  5539. /*Makes a bounded vis object's XNAME*/
  5540. {
  5541.     ObjPtr dataset, name;
  5542.  
  5543.     MakeVar(object, MAINDATASET);
  5544.     dataset = GetVar(object, MAINDATASET);
  5545.     if (!dataset)
  5546.     {
  5547.     MakeVar(object, REPOBJ);
  5548.     dataset = GetVar(object, REPOBJ);
  5549.     }
  5550.     if (dataset)
  5551.     {
  5552.     MakeVar(dataset, XNAME);
  5553.     name = GetVar(dataset, XNAME);
  5554.     }
  5555.     else
  5556.     {
  5557.     name = NULLOBJ;
  5558.     }
  5559.     if (name)
  5560.     {
  5561.     SetVar(object, XNAME, name);
  5562.     }
  5563.     else
  5564.     {
  5565.     SetVar(object, XNAME, NewString("X"));
  5566.     }
  5567. }
  5568.  
  5569. static ObjPtr MakeBoundedYName(object)
  5570. ObjPtr object;
  5571. /*Makes a bounded vis object's YNAME*/
  5572. {
  5573.     ObjPtr dataset, name;
  5574.  
  5575.     MakeVar(object, MAINDATASET);
  5576.     dataset = GetVar(object, MAINDATASET);
  5577.     if (!dataset)
  5578.     {
  5579.     MakeVar(object, REPOBJ);
  5580.     dataset = GetVar(object, REPOBJ);
  5581.     }
  5582.     if (dataset)
  5583.     {
  5584.     MakeVar(dataset, YNAME);
  5585.     name = GetVar(dataset, YNAME);
  5586.     }
  5587.     else
  5588.     {
  5589.     name = NULLOBJ;
  5590.     }
  5591.     if (name)
  5592.     {
  5593.     SetVar(object, YNAME, name);
  5594.     }
  5595.     else
  5596.     {
  5597.     SetVar(object, YNAME, NewString("Y"));
  5598.     }
  5599. }
  5600.  
  5601. static ObjPtr MakeBoundedZName(object)
  5602. ObjPtr object;
  5603. /*Makes a bounded vis object's XNAME*/
  5604. {
  5605.     ObjPtr dataset, name;
  5606.  
  5607.     MakeVar(object, MAINDATASET);
  5608.     dataset = GetVar(object, MAINDATASET);
  5609.     if (!dataset)
  5610.     {
  5611.     MakeVar(object, REPOBJ);
  5612.     dataset = GetVar(object, REPOBJ);
  5613.     }
  5614.     if (dataset)
  5615.     {
  5616.     MakeVar(dataset, ZNAME);
  5617.     name = GetVar(dataset, ZNAME);
  5618.     }
  5619.     else
  5620.     {
  5621.     name = NULLOBJ;
  5622.     }
  5623.     if (name)
  5624.     {
  5625.     SetVar(object, ZNAME, name);
  5626.     }
  5627.     else
  5628.     {
  5629.     SetVar(object, ZNAME, NewString("Z"));
  5630.     }
  5631. }
  5632.  
  5633. static ObjPtr MakeVisAppearance(object)
  5634. ObjPtr object;
  5635. /*Makes a vis object's appearance*/
  5636. {
  5637.     SetVar(object, APPEARANCE, ObjTrue);
  5638.     ImInvalid(object);
  5639. }
  5640.  
  5641. static ObjPtr DropInSizeCorral(corral, object, x, y)
  5642. ObjPtr corral, object;
  5643. int x, y;
  5644. /*Drops an icon in a size corral*/
  5645. {
  5646.     ObjPtr visObj;
  5647.     ObjPtr fieldObj;
  5648.     ObjPtr icon;
  5649.     ObjPtr name;
  5650.     ObjPtr defaultIcon;
  5651.     ObjPtr contents;
  5652.     ObjPtr button;
  5653.     long info;
  5654.  
  5655.     /*Find the visualization object*/
  5656.     visObj = GetObjectVar("DropInSizeCorral", corral, REPOBJ);
  5657.     if (!visObj)
  5658.     {
  5659.     return ObjFalse;
  5660.     }
  5661.  
  5662.     /*Get the field object*/
  5663.     fieldObj = GetObjectVar("DropInSizeCorral", object, REPOBJ);
  5664.     if (!fieldObj)
  5665.     {
  5666.     return ObjFalse;
  5667.     }
  5668.  
  5669.     info = GetDatasetInfo(fieldObj);
  5670.     if ((info & DS_HASGEOMETRY))
  5671.     {
  5672.     WarnUser(CW_NOGEOMETRYERROR);
  5673.     return ObjFalse;
  5674.     }
  5675.  
  5676.     /*Create an icon for it*/
  5677.     name = GetStringVar("DropInSizeCorral", fieldObj, NAME);
  5678.     if (!name)
  5679.     {
  5680.     return ObjFalse;
  5681.     }
  5682.  
  5683.     defaultIcon = GetVar(fieldObj, DEFAULTICON);
  5684.     if (defaultIcon)
  5685.     {
  5686.     ObjPtr locArray;
  5687.     real loc[2];
  5688.     icon = NewObject(defaultIcon, 0);
  5689.     SetVar(icon, NAME, name);
  5690.     loc[0] = x;
  5691.     loc[1] = y;
  5692.     locArray = NewRealArray(1, 2L);
  5693.     CArray2Array(locArray, loc);
  5694.     SetVar(icon, ICONLOC, locArray);
  5695.     }
  5696.     else
  5697.     {
  5698.     icon = NewIcon(x, y, ICONQUESTION, GetString(name));
  5699.     }
  5700.     
  5701.     /*Make the icon ball to the field*/
  5702.     SetVar(icon, REPOBJ, fieldObj);
  5703.  
  5704.     /*Make it the only icon in the corral*/
  5705.     contents = NewList();
  5706.     PrefixList(contents, icon);
  5707.     SetVar(corral, CONTENTS, contents);
  5708.     SetVar(contents, PARENT, corral);
  5709.     SetVar(icon, PARENT, corral);
  5710.     RecalcScroll(corral);
  5711.  
  5712.     /*Make this object the sized object*/
  5713.     SetVar(visObj, SIZEOBJ, fieldObj);
  5714.  
  5715.     ImInvalid(visObj);
  5716.     ImInvalid(corral);
  5717.     return ObjTrue;
  5718. }
  5719.  
  5720. static ObjPtr AddSizedControls(object, panelContents)
  5721. ObjPtr object, panelContents;
  5722. /*Adds controls to a sized object*/
  5723. {
  5724.     ObjPtr control, button, checkBox, corral, sw, textBox, slider, icon, radioGroup;
  5725.     ObjPtr sizeObj, titleBox;
  5726.     ObjPtr var;
  5727.     int width, left, right, top, bottom, cellHeight, m1, m2;
  5728.     real initValue;
  5729.     real baseColor[3];
  5730.     real hs[2], dummy;
  5731.     ObjPtr parent;
  5732.  
  5733.     /*Get the parent*/
  5734.     parent = GetObjectVar("AddSizedControls", panelContents, PARENT);
  5735.  
  5736.     width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
  5737.     left = MAJORBORDER;
  5738.  
  5739.     cellHeight = ONECORRALHEIGHT;
  5740.  
  5741.     /*Precalculate the midlines for convenience*/
  5742.     m1 = CWINHEIGHT - MAJORBORDER - cellHeight / 2;
  5743.     m1 += MINORBORDER;
  5744.     m2 = m1 - cellHeight - MAJORBORDER - TEXTBOXHEIGHT - TEXTBOXSEP;
  5745.  
  5746.     /*Create the size source corral*/
  5747.     corral = NewIconCorral(NULLOBJ,
  5748.                left, left + ONECORRALWIDTH,
  5749.                m2 - ONECORRALHEIGHT / 2,
  5750.                m2 + ONECORRALHEIGHT / 2, 0);
  5751.     SetVar(corral, SINGLECORRAL, ObjTrue);
  5752.     SetVar(corral, TOPDOWN, ObjTrue);
  5753.     SetVar(corral, NAME, NewString("Size Field"));
  5754.     PrefixList(panelContents, corral);
  5755.     SetVar(corral, HELPSTRING,
  5756.     NewString("This corral shows the dataset that is used to \
  5757. determine the size of the visualization object.  \
  5758. To replace it with another dataset, drag the icon of the other \
  5759. dataset into this corral."));
  5760.     SetVar(corral, PARENT, panelContents);
  5761.     SetVar(corral, REPOBJ, object);
  5762.     SetMethod(corral, DROPINCONTENTS, DropInSizeCorral);
  5763.  
  5764.     /*Create the size source text box*/
  5765.     textBox = NewTextBox(left, left + ONECORRALWIDTH, 
  5766.              m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP - TEXTBOXHEIGHT,
  5767.              m2 - ONECORRALHEIGHT / 2 - TEXTBOXSEP,
  5768.              0, "Size Field Text", "Size Field");
  5769.     PrefixList(panelContents, textBox);
  5770.     SetVar(textBox, PARENT, panelContents);
  5771.     SetTextAlign(textBox, CENTERALIGN);
  5772.  
  5773.     left += ONECORRALWIDTH + MINORBORDER;
  5774.     sizeObj = GetVar(object, SIZEOBJ);
  5775.     if (sizeObj)
  5776.     {
  5777.     ObjPtr name, defaultIcon;
  5778.     /*Drop icon in corral, if need be*/
  5779.     name = GetVar(sizeObj, NAME);
  5780.     defaultIcon = GetVar(sizeObj, DEFAULTICON);
  5781.     if (defaultIcon)
  5782.     {
  5783.         icon = NewObject(defaultIcon, 0);
  5784.         SetVar(icon, NAME, name);
  5785.     }
  5786.     else
  5787.     {
  5788.         icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
  5789.         }
  5790.     SetVar(icon, REPOBJ, sizeObj);
  5791.     SetVar(icon, ICONLOC, NULLOBJ);
  5792.         DropIconInCorral(corral, icon);
  5793.     }
  5794.  
  5795.     /*Create the constant size control*/
  5796.     var = GetRealVar("AddSizedControls", object, SIZECONSTANT);
  5797.     if (!var)
  5798.     {
  5799.     SetVar(object, SIZECONSTANT, NewReal(0.0));
  5800.     }
  5801.     textBox = NewTextBox(MAJORBORDER, left - MINORBORDER, 
  5802.             m1 - EDITBOXHEIGHT / 2,
  5803.             m1 + EDITBOXHEIGHT / 2, 
  5804.             EDITABLE + WITH_PIT + ONE_LINE,
  5805.             "Fixed Size", "");
  5806.     PrefixList(panelContents, textBox);
  5807.     SetVar(textBox, PARENT, panelContents);
  5808.     SetVar(textBox, HELPSTRING, NewString("This text box gives a constant \
  5809. size when it is selected by the switch."));
  5810.     SetVar(textBox, WHICHVAR, NewSymbol(SIZECONSTANT));
  5811.     SetTextAlign(textBox, RIGHTALIGN);
  5812.     AssocTextRealControlWithVar(textBox, object, SIZECONSTANT, 0.0, plusInf, TR_NE_TOP);
  5813.  
  5814.     /*Create the text box*/
  5815.     textBox = NewTextBox(MAJORBORDER - 20, left - MINORBORDER + 20, 
  5816.              m1 - EDITBOXHEIGHT / 2 - TEXTBOXSEP - 2 * TEXTBOXHEIGHT,
  5817.              m1 - EDITBOXHEIGHT / 2 - TEXTBOXSEP,
  5818.              0, "Fixed Size Text", "Fixed Size");
  5819.     PrefixList(panelContents, textBox);
  5820.     SetVar(textBox, PARENT, panelContents);
  5821.     SetTextAlign(textBox, CENTERALIGN);
  5822.     SetVar(textBox, REPOBJ, object);
  5823.  
  5824.     /*Create the choice switch*/
  5825.     var = GetIntVar("AddSizedControls", object, SIZESWITCH);
  5826.     if (!var)
  5827.     {
  5828.     SetVar(object, SIZESWITCH, NewInt(0));
  5829.     }
  5830.     sw = NewSwitch(left, left + SWITCHWIDTH,
  5831.             m2 - cellHeight / 2 - (MAJORBORDER + TEXTBOXHEIGHT + TEXTBOXSEP) / 2,
  5832.             m1 + cellHeight / 2 + (MAJORBORDER + TEXTBOXHEIGHT + TEXTBOXSEP) / 2,
  5833.             2, 0, var ? GetInt(var) : 0,
  5834.             "Size Switch");
  5835.     PrefixList(panelContents, sw);
  5836.     SetVar(sw, PARENT, panelContents);
  5837.     SetVar(sw, REPOBJ, object);
  5838.     SetVar(sw, HELPSTRING, NewString("This switch controls whether the \
  5839. soze of the visualization object comes from a \
  5840. field or from a fixed size."));
  5841.     AssocDirectControlWithVar(sw, object, SIZESWITCH);
  5842.  
  5843.     left += SWITCHWIDTH + MINORBORDER;
  5844.  
  5845.     /*Create the * text box*/
  5846.     right = left + MINORBORDER;
  5847.     textBox = NewTextBox(left, right + MINORBORDER, 
  5848.             m1 - EDITBOXHEIGHT / 2,
  5849.             m1 + EDITBOXHEIGHT / 2, 
  5850.             0,
  5851.             "Splat", "*");
  5852.     PrefixList(panelContents, textBox);
  5853.     SetVar(textBox, PARENT, panelContents);
  5854.     SetTextFont(textBox, "Courier-Bold");
  5855.     SetTextSize(textBox, 18);
  5856.     left = right + MINORBORDER;
  5857.  
  5858.     /*Create the size factor*/
  5859.     var = GetVar(object, SIZEFACTOR);
  5860.     if (!var)
  5861.     {
  5862.     SetVar(object, SIZEFACTOR, NewReal(0.0));
  5863.     }
  5864.     right = left + SIZEEDITWIDTH;
  5865.     textBox = TemplateTextBox(VisSizeTemplate, "Size Factor", 
  5866.             EDITABLE + WITH_PIT + ONE_LINE,
  5867.             "");
  5868.     PrefixList(panelContents, textBox);
  5869.     SetVar(textBox, PARENT, panelContents);
  5870.     SetVar(textBox, HELPSTRING, NewString("This text box gives a multiplier \
  5871. for the size provided by the switch."));
  5872.     SetVar(textBox, WHICHVAR, NewSymbol(SIZEFACTOR));
  5873.     AssocTextRealControlWithVar(textBox, object, SIZEFACTOR, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  5874.     SetTextAlign(textBox, RIGHTALIGN);
  5875.  
  5876.     /*Create the text box*/
  5877.     textBox = TemplateTextBox(VisSizeTemplate, "Factor Text",
  5878.             0, "Factor");
  5879.     PrefixList(panelContents, textBox);
  5880.     SetVar(textBox, PARENT, panelContents);
  5881.     SetTextAlign(textBox, CENTERALIGN);
  5882.     SetVar(textBox, REPOBJ, object);
  5883.     left = right + MINORBORDER;
  5884.  
  5885.     /*Create the + text box*/
  5886.     right = left + MINORBORDER;
  5887.     textBox = TemplateTextBox(VisSizeTemplate, "Plus", 0, "+");
  5888.     PrefixList(panelContents, textBox);
  5889.     SetVar(textBox, PARENT, panelContents);
  5890.     SetTextFont(textBox, "Courier-Bold");
  5891.     SetTextSize(textBox, 18);
  5892.     left = right + MINORBORDER;
  5893.  
  5894.     /*Create the size offset*/
  5895.     var = GetRealVar("AddSizedControls", object, SIZEOFFSET);
  5896.     if (!var)
  5897.     {
  5898.     SetVar(object, SIZEOFFSET, NewReal(0.0));
  5899.     }
  5900.     right = left + SIZEEDITWIDTH;
  5901.     textBox = TemplateTextBox(VisSizeTemplate, "Size Offset", 
  5902.             EDITABLE + WITH_PIT + ONE_LINE, "");
  5903.     PrefixList(panelContents, textBox);
  5904.     SetVar(textBox, PARENT, panelContents);
  5905.     SetVar(textBox, HELPSTRING, NewString("This text box gives an offset \
  5906. for the size provided by the switch, multiplied by the multiplier."));
  5907.     AssocTextRealControlWithVar(textBox, object, SIZECONSTANT, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
  5908.     SetTextAlign(textBox, RIGHTALIGN);
  5909.  
  5910.     /*Create the text box*/
  5911.     textBox = TemplateTextBox(VisSizeTemplate, "Offset Text", 0, "Offset");
  5912.     PrefixList(panelContents, textBox);
  5913.     SetVar(textBox, PARENT, panelContents);
  5914.     SetTextAlign(textBox, CENTERALIGN);
  5915.     SetVar(textBox, REPOBJ, object);
  5916.     left = right + MINORBORDER;
  5917.  
  5918.     return ObjTrue;
  5919. }
  5920.  
  5921. Bool cacheMade;        /*Global to indicate cache was made*/
  5922.  
  5923. static ObjPtr MakeCachedOpaque(object)
  5924. ObjPtr object;
  5925. /*Routine to make opaque cache*/
  5926. {
  5927.     SetVar(object, CACHEDOPAQUE, GetVar(object, CACHEDOPAQUE));
  5928.     cacheMade = true;
  5929.     return ObjTrue;
  5930. }
  5931.  
  5932. static ObjPtr MakeCachedTransparent(object)
  5933. ObjPtr object;
  5934. /*Routine to make transparent cache*/
  5935. {
  5936.     SetVar(object, CACHEDTRANSPARENT, GetVar(object, CACHEDTRANSPARENT));
  5937.     cacheMade = true;
  5938.     return ObjTrue;
  5939. }
  5940.  
  5941. void InitVisObjects()
  5942. /*Initializes the visualization objects.*/
  5943. {
  5944.     ObjPtr icon;
  5945.     ObjPtr array, var;
  5946.     ObjPtr list;
  5947.     real *elements;
  5948.  
  5949.     allVisObjClasses = NewList();
  5950.     AddToReferenceList(allVisObjClasses);
  5951.  
  5952.     visIcon = NewIcon(0, 0, ICONQUESTION, "Visualization Object");
  5953.     AddToReferenceList(visIcon);
  5954.     SetVar(visIcon, HELPSTRING,
  5955.     NewString("You can create a copy of this visualization, which you can \
  5956. then modify, by selecting the icon and choosing the Duplicate item in the Object menu.  \
  5957. You can show this visualization object in another window as well by dragging the icon into \
  5958. the corral of the other window.  \
  5959. You can show controls that affect this visualization by selecting the icon and \
  5960. choosing Show Controls from the Object menu."));
  5961.  
  5962.     visClass = NewObject(NULLOBJ, 0);
  5963.     AddToReferenceList(visClass);
  5964.     DeclareDependency(visClass, NAME, MAINDATASET);
  5965.     DeclareDependency(visClass, NAME, TEMPLATEP);
  5966.     SetMethod(visClass, NAME, MakeVisName);
  5967.     SetVar(visClass, CLASSID, NewInt(CLASS_VISOBJ));
  5968.     SetVar(visClass, MULTIDRAW, ObjTrue);
  5969.     SetVar(visClass, DOUBLECLICK, NewString(OF_SHOW_CONTROLS));
  5970.     SetMethod(visClass, NEWCTLWINDOW, ShowVisControls);
  5971.     SetMethod(visClass, SHOWCONTROLS, NewControlWindow);
  5972.     SetMethod(visClass, HIDE, HideVisObject);
  5973.     SetMethod(visClass, SHOW, ShowVisObject);
  5974.     AddSnapVar(visClass, HIDDEN);
  5975.     SetMethod(visClass, CLONE, CloneVisObject);
  5976.     SetMethod(visClass, PREFIXDATASETS, PrefixMainDataset);
  5977.     SetMethod(visClass, DELETE, DeleteObject);
  5978.     SetMethod(visClass, DUPLICATE, DuplicateSpaceObject);
  5979.     SetMethod(visClass, LOCALCOPY, MakeLocalCopy);
  5980.     SetMethod(visClass, VISUALIZE, VisualizeVisObject);
  5981.     SetMethod(visClass, APPEARANCE, MakeVisAppearance);
  5982.     SetVar(visClass, XSCALE, NewReal(1.0));
  5983.     SetVar(visClass, YSCALE, NewReal(1.0));
  5984.     SetVar(visClass, ZSCALE, NewReal(1.0));
  5985.  
  5986.     
  5987.     visAxes = NewObject(visClass, 0);
  5988.     AddToReferenceList(visAxes);
  5989.     icon = NewIcon(0, 0, ICONAXES, "Axes");
  5990.     SetVar(icon, HELPSTRING,
  5991.     NewString("Select this icon to show controls to display the axes of the \
  5992. visualization object."));
  5993.     SetVar(visAxes, CONTROLICON, icon);
  5994.     SetMethod(visAxes, ADDCONTROLS, AddAxesControls);
  5995.     SetMethod(visAxes, AXISMAJORSTEP, MakeAxesMajorStep);
  5996.     SetMethod(visAxes, AXISDIVISIONS, MakeAxesDivisions);
  5997.     SetVar(visAxes, DRAWNAMES, NewInt(0));
  5998.  
  5999.     visBounded = NewObject(visAxes, 0);
  6000.     AddToReferenceList(visBounded);
  6001.     SetMethod(visBounded, DRAW, DrawBounded);
  6002.     SetMethod(visBounded, ADDCONTROLS, AddBoundedControls);
  6003.     SetMethod(visBounded, BOUNDS, MakeFormBounds);
  6004.     SetMethod(visBounded, TICLENGTH, MakeBoundedTicLength);
  6005.     icon = NewIcon(0, 0, ICONBOX, "Bounds");
  6006.     SetVar(icon, HELPSTRING,
  6007.     NewString("Select this icon to show controls for a bounded object, such \
  6008. as whether to draw bounds, axes, and tic marks."));
  6009.     SetVar(visBounded, CONTROLICON, icon);
  6010.     SetMethod(visBounded, XNAME, MakeBoundedXName);
  6011.     SetMethod(visBounded, YNAME, MakeBoundedYName);
  6012.     SetMethod(visBounded, ZNAME, MakeBoundedZName);
  6013.  
  6014.     visWalls = NewObject(visBounded, 0);
  6015.     AddToReferenceList(visWalls);
  6016.     SetMethod(visWalls, DRAW, DrawWalls);
  6017.     icon = NewIcon(0, 0, ICONWALLS, "Walls");
  6018.     SetVar(icon, HELPSTRING,
  6019.     NewString("Select this icon to show controls to display the walls of the \
  6020. visualization object."));
  6021.     SetVar(visWalls, CONTROLICON, icon);
  6022.     SetMethod(visWalls, ADDCONTROLS, AddWallsControls);
  6023.     SetVar(visWalls, DRAWBACKGROUND, ObjTrue);
  6024.     SetVar(visWalls, DRAWOUTLINE, ObjFalse);
  6025.     SetVar(visWalls, DRAWGRID, ObjFalse);
  6026.     array = NewRealArray(1, 3L);
  6027.     elements = ELEMENTS(array);
  6028.     elements[0] = 0.5;
  6029.     elements[1] = 0.5;
  6030.     elements[2] = 0.5;
  6031.     SetVar(visWalls, WALLPANELCOLOR, array);
  6032.     array = NewRealArray(1, 3L);
  6033.     elements = ELEMENTS(array);
  6034.     elements[0] = 0.75;
  6035.     elements[1] = 0.75;
  6036.     elements[2] = 0.75;
  6037.     SetVar(visWalls, WALLLINESCOLOR, array);
  6038.     
  6039.     /*Class for any colored object*/
  6040.     visColored = NewObject(visWalls, 0);
  6041.     AddToReferenceList(visColored);
  6042.     icon = NewIcon(0, 0, ICONCOLOR, "Color");
  6043.     SetVar(icon, HELPSTRING,
  6044.     NewString("Select this icon to show controls for a colored object, such \
  6045. as whether to color using a fixed color or a scalar field."));
  6046.     SetVar(visColored, CONTROLICON, icon);
  6047.     SetMethod(visColored, ADDCONTROLS, AddColoredControls);
  6048.     SetVar(visColored, COLORSHADING, ObjTrue);    /*Default smooth shaded*/
  6049.     DeclareDependency(visColored, PICCOLORED, INTERPCOLORS);
  6050.     DeclareDependency(visColored, PICCOLORED, COLORS);
  6051.     DeclareDependency(visColored, PICCOLORED, COLOROBJ);
  6052.     DeclareDependency(visColored, PICCOLORED, CPALETTE);
  6053.     DeclareDependency(visColored, CACHEDOPAQUE, PICCOLORED);
  6054.     DeclareDependency(visColored, CACHEDTRANSPARENT, PICCOLORED);
  6055.     SetVar(visColored, COLORS, NewInt(0));
  6056.     DeclareDependency(visColored, APPEARANCE, PICCOLORED);
  6057.     DeclareIndirectDependency(visColored, PICCOLORED, CPALETTE, CHANGED);
  6058.     SetMethod(visColored, PICCOLORED, MakePicColored);
  6059.     var = NewRealArray(1, 3L);
  6060.     elements = ELEMENTS(var);
  6061.     elements[0] = elements[1] = elements[2] = 1.0;
  6062.     SetVar(visColored, BASECOLOR, var);
  6063.     SetVar(visColored, BRIGHTNESS, NewReal(1.0));
  6064.     SetVar(visColored, INTERPCOLORS, ObjTrue);    /*Interpolate colors*/
  6065.  
  6066.     DeclareDependency(visColored, CPALETTE, COLORS);
  6067.     DeclareDependency(visColored, CPALETTE, BRIGHTNESS);
  6068.     DeclareDependency(visColored, CPALETTE, BASECOLOR);
  6069.     DeclareDependency(visColored, CPALETTE, COLOROBJ);
  6070.     DeclareIndirectDependency(visColored, CPALETTE, COLOROBJ, PALETTESET);
  6071.     SetMethod(visColored, CPALETTE, MakeColoredPalette);
  6072.     SetMethod(visColored, PREFIXDATASETS, PrefixColoredDatasets);
  6073.     SetVar(visColored, INTERPOLATEP, ObjTrue);
  6074.  
  6075.     /*Class for any object with dots*/
  6076.     visDots = NewObject(visColored, 0);
  6077.     icon = NewIcon(0, 0, ICONDOTS, "Dots");
  6078.     SetVar(visDots, DEPTHCUEDOTS, ObjFalse);
  6079.     SetMethod(visDots, ADDCONTROLS, AddDotsControls);
  6080.     SetVar(icon, HELPSTRING,
  6081.     NewString("Select this icon to show controls for drawing dots in the \
  6082. visualization object."));
  6083.     SetVar(visDots, CONTROLICON, icon);
  6084.     SetMethod(visDots, PICKPOINT, PickVisDots);
  6085.     SetMethod(visDots, DRAW, DrawVisDots);
  6086.     DeclareDependency(visDots, SURFACE, TIME);
  6087.     DeclareDependency(visDots, PICCOLORED, SURFACE);
  6088.     DeclareDependency(visDots, APPEARANCE, SURFACE);
  6089.     DeclareDependency(visDots, SURFACE, MAINDATASET);
  6090.     DeclareIndirectDependency(visDots, SURFACE, MAINDATASET, CHANGED);
  6091.     SetVar(visDots, CACHEGRAPHICS, ObjFalse);
  6092.     DeclareDependency(visDots, CACHEDOPAQUE, SURFACE);
  6093.     DeclareDependency(visDots, CACHEDOPAQUE, CACHEGRAPHICS);
  6094.     DeclareDependency(visDots, CACHEDTRANSPARENT, SURFACE);
  6095.     DeclareDependency(visDots, CACHEDTRANSPARENT, CACHEGRAPHICS);
  6096.     SetMethod(visDots, CACHEDOPAQUE, MakeCachedOpaque);
  6097.     SetMethod(visDots, CACHEDTRANSPARENT, MakeCachedTransparent);
  6098.  
  6099.     /*Class for any object with lines*/
  6100.     visLines = NewObject(visDots, 0);
  6101.     SetVar(visLines, DRAWWIREFRAME, ObjTrue);
  6102.     SetVar(visLines, DEPTHCUELINES, ObjFalse);
  6103.     icon = NewIcon(0, 0, ICONLINES, "Lines");
  6104.     SetMethod(visLines, ADDCONTROLS, AddLineControls);
  6105.     SetVar(icon, HELPSTRING,
  6106.     NewString("Select this icon to show controls for drawing lines in the \
  6107. visualization object."));
  6108.     SetVar(visLines, CONTROLICON, icon);
  6109.     SetMethod(visLines, DRAW, DrawVisLines);
  6110.  
  6111.     /*Class for any object with a lit surface*/
  6112.     visSurface = NewObject(visLines, 0);
  6113.     AddToReferenceList(visSurface);
  6114.     SetVar(visSurface, DRAWSURFACE, ObjTrue);
  6115.     SetVar(visSurface, DRAWWIREFRAME, ObjFalse);
  6116.     icon = NewIcon(0, 0, ICONMATERIAL, "Surface");
  6117.     SetVar(icon, HELPSTRING,
  6118.     NewString("Select this icon to show controls for a surface, such \
  6119. as surface highlights and translucency."));
  6120.     SetMethod(visSurface, ADDCONTROLS, AddSurfaceControls);
  6121.     SetVar(visSurface, CONTROLICON, icon);
  6122.     SetVar(visSurface, LIGHTSHADING, NewInt(2)); /*Default smooth shaded*/
  6123.     SetVar(visSurface, SHINVAL, NewReal(80.0));
  6124.     SetVar(visSurface, SPECVAL, NewReal(0.2));
  6125.     SetMethod(visSurface, DRAW, DrawVisSurface);
  6126.     var = NewRealArray(1, 3L);
  6127.     elements = ELEMENTS(var);
  6128.     elements[0] = elements[1] = elements[2] = 1.0;
  6129.     SetVar(visSurface, HIGHLIGHTCOLOR, var);
  6130.  
  6131.     /*Class for any object with a deformable surface*/
  6132.     visDeformed = NewObject(visSurface, 0);
  6133.     AddToReferenceList(visDeformed);
  6134.     SetMethod(visDeformed, ADDCONTROLS, AddDeformedControls);
  6135.     icon = NewIcon(0, 0, ICONDEFORM, "Deform");
  6136.     SetVar(icon, HELPSTRING,
  6137.     NewString("Select this icon to show controls that deform a visualization object."));
  6138.     SetVar(visDeformed, CONTROLICON, icon);
  6139.  
  6140.     SetVar(visDeformed, DEFFACTOR, NewReal(1.0));
  6141.     SetVar(visDeformed, DEFCONSTANT, NewReal(0.0));
  6142.     SetVar(visDeformed, DEFOFFSET, NewReal(0.0));
  6143.     SetVar(visDeformed, DEFORMSWITCH, NewInt(0));
  6144.     DeclareIndirectDependency(visDeformed, SURFACE, DEFORMOBJ, CHANGED);
  6145.     DeclareDependency(visDeformed, SURFACE, DEFORMOBJ);
  6146.     DeclareDependency(visDeformed, SURFACE, DEFCONSTANT);
  6147.     DeclareDependency(visDeformed, SURFACE, DEFOFFSET);
  6148.     DeclareDependency(visDeformed, SURFACE, DEFFACTOR);
  6149.     DeclareDependency(visDeformed, SURFACE, DEFORMSWITCH);
  6150.     DeclareDependency(visDeformed, PICDEFORMED, SURFACE);
  6151.     SetVar(visDeformed, REVERSESENSE, NewInt(0));
  6152.     /*DIKEO dependency on INTERPwhatever*/
  6153.     SetMethod(visDeformed, PICDEFORMED, MakePicDeformed);
  6154.  
  6155.     /*Class for a geometry object*/
  6156.     visGeometryClass = NewObject(visSurface, 0);
  6157.     AddToReferenceList(visGeometryClass);
  6158.     SetMethod(visGeometryClass, ADDCONTROLS, AddGeometryControls);
  6159.     icon = NewIcon(0, 0, ICONGEOMETRY, "Geometry");
  6160.     SetVar(visGeometryClass, CONTROLICON, icon);
  6161.     SetVar(visGeometryClass, SPHERESUBDIV, NewInt(2));
  6162.     SetVar(visGeometryClass, FRUSTUMSUBDIV, NewInt(2));
  6163.     SetVar(visGeometryClass, CAPENDSP, ObjTrue);
  6164.  
  6165.     DeclareDependency(visGeometryClass, SURFACE, SPHERESUBDIV);
  6166.     DeclareDependency(visGeometryClass, SURFACE, FRUSTUMSUBDIV);
  6167.     DeclareDependency(visGeometryClass, SURFACE, CAPENDSP);
  6168.  
  6169.     /*Class for any object which can be sized*/
  6170.     visSized = NewObject(visGeometryClass, 0);
  6171.     AddToReferenceList(visSized);
  6172.     SetMethod(visSized, ADDCONTROLS, AddSizedControls);
  6173.     icon = NewIcon(0, 0, ICONVISSIZE, "Size");
  6174.     SetVar(icon, HELPSTRING,
  6175.     NewString("Select this icon to show controls to determine \
  6176. the size of the elements of the visualization object."));
  6177.     SetVar(visSized, CONTROLICON, icon);
  6178.  
  6179.     SetVar(visSized, SIZEFACTOR, NewReal(1.0));
  6180.     DeclareIndirectDependency(visSized, SURFACE, SIZEOBJ, CHANGED);
  6181.     DeclareDependency(visSized, SURFACE, SIZEOBJ);
  6182.     DeclareDependency(visSized, SURFACE, SIZECONSTANT);
  6183.     DeclareDependency(visSized, SURFACE, SIZEOFFSET);
  6184.     DeclareDependency(visSized, SURFACE, SIZEFACTOR);
  6185.     DeclareDependency(visSized, SURFACE, SIZESWITCH);
  6186.     SetVar(visSized, SIZESWITCH, NewInt(0));
  6187.  
  6188.     /*Class for a geometry picture*/
  6189.     geoPictureClass = NewObject(visGeometryClass, 0);
  6190.     AddToReferenceList(geoPictureClass);
  6191.     SetVar(geoPictureClass, NAME, NewString("Geometry"));
  6192.     icon = NewObject(visIcon, 0);
  6193.     SetVar(icon, NAME, NewString("Geometry"));
  6194.     SetVar(icon, WHICHICON, NewInt(ICONGEOMETRY));
  6195.     SetVar(icon, HELPSTRING,
  6196.     NewString("This icon represents a geometry object, which shows a \
  6197. geometry dataset directly as a picture in the space."));
  6198.     SetVar(geoPictureClass, DEFAULTICON, icon);
  6199.     SetMethod(geoPictureClass, BOUNDS, MakeGeoPictureBounds);
  6200.     SetMethod(geoPictureClass, SURFACE, MakeGeoPictureSurface);
  6201.     SetMethod(geoPictureClass, INITIALIZE, GeometryInit);
  6202.     DeclareIndirectDependency(geoPictureClass, SURFACE, REPOBJ, CHANGED);
  6203.     SetMethod(geoPictureClass, PICCOLORED, MakeGeoPicColored);
  6204.  
  6205.     InitArrows();
  6206.     InitIsosurfaces();
  6207.     InitMeshes();
  6208.     InitContours();
  6209.     InitTraces();
  6210.     InitSticks();
  6211.     InitPoints();
  6212.     InitBalls();
  6213.     InitNumbers();
  6214.  
  6215.     DefineVisMapping(DS_HASGEOMETRY, -1, -1, -1, geoPictureClass);
  6216.     DefineVisMapping(DS_HASNEWGEOMETRY | DS_HASFORM | DS_UNSTRUCTURED, -1, -1, -1, geoPictureClass);
  6217. }
  6218.  
  6219. void KillVisObjects()
  6220. /*Kills the visobjects*/
  6221. {
  6222.     KillNumbers();
  6223.     KillBalls();
  6224.     KillPoints();
  6225.     KillSticks();
  6226.     KillArrows();
  6227.     KillContours();
  6228.     KillIsosurfaces();
  6229.     KillTraces();
  6230.     DeleteThing(geoPictureClass);
  6231.     DeleteThing(visDeformed);
  6232.     DeleteThing(visSurface);
  6233.     DeleteThing(visColored);
  6234.     DeleteThing(visAxes);
  6235.     DeleteThing(visWalls);
  6236.     DeleteThing(visBounded);
  6237.     DeleteThing(visClass);
  6238.     DeleteThing(visIcon);
  6239.     while (nVisSerials)
  6240.     {
  6241.     --nVisSerials;
  6242.     Free(visSerials[nVisSerials] . name);
  6243.     }
  6244.     DeleteThing(allVisObjClasses);
  6245. }
  6246.  
  6247.